【php】file_get_contents()やブラウザで「に視聴すã‚」のような文字化けがするのは、取得したデータが「utf-8」なのに「ISO-8859-1」と勘違いして「ISO-8859-1」⇒「utf-8」にデコード処理して表示しているためだった

PC

file_get_contents()で色々なサイトからデータを取っていると、特定のサイトでどうしても文字化けが出て解消できない。

mb_convert_encoding()でsjisからutf8にしたり、逆にしたりしたが駄目。

ブラウザの表示エンコードsjis、euc、iso-2202など様々試したが駄目。

取得htmlには<meta charset="UTF-8″>の記載あり。

chromeの開発者ツールでresponse-headersのcontent-typeのcharsetを見ても「UTF-8」となっている。

BOM有になっているのかと考え、BOMを削除する処理を入れたが駄目。

エンコードマニアックス」(https://www.encodemaniax.com/)というサイトで、本来出るべき文字列を調べたら、「MIME Decode」の欄に同じ文字化けの文字列が出た。

エンコードではなくデコードなのが味噌だがこの時点ではよく理解できていなかった。

MIMEエンコード周りの変換関数を調べて、mb_encode_mimeheader($str)やらiconv_mime_decode($str)やらutf8_encode($str)やら試したが駄目($strはfile_get_contents()の出力文字列)。

もじばけらった」(https://lab.kiki-verb.com/mojibakeratta/)というサイトで、本来出るべき文字列を入力して、入力と出力の文字コードの組み合わせを色々試したら、「utf-8」と「ISO-8859-1」の組み合わせで、同じ文字化けの文字列が出た。

「ISO-8859-1」と「MIME Decode」の関係はよくわからない。

引き続いて「ISO-8859-1」のエンコード・デコード周りの関数を調べると、iconv関数がでた。

で、iconv('ISO-8859-1′ ,’UTF-8’,$str)を試したが駄目。

最後に’UTF-8’と’ISO-8859-1’を入れ替えて、iconv( 'UTF-8′,’ISO-8859-1’,$str)としたところ、解決。

状況を整理すると、取得したデータはUTF-8だったが、どいうわけかfile_get_contents()が、「ISO-8859-1」エンコードされたデータと認識し、「ISO-8859-1」デコードした文字列を出力として返していた模様。

file_get_contents()の出力文字列を「UTF-8」から「ISO-8859-1」にエンコードすると、元の「UTF-8」形式に戻った。

取得htmlには<meta charset="UTF-8″>の記載があり、また、content-typeのcharsetもUTF-8となっているため、なぜfile_get_contents()が「ISO-8859-1」と認識したかは不明。

また、file_get_contents()が「UTF-8」として認識してそのまま出力しているのか、「ISO-8859-1」と認識してデコードした文字列を出力しているのかを判別する方法は見つからず。

いずれの場合もfile_get_contents()は「UTF-8」で出力したつもりでいる。

出力された文字列が「UTF-8」なのか「ISO-8859-1」デコードなのかを判別する方法も見つかっておらず。

charsetを指定してfile_get_contents()で取得する方法も見つからず。

file_get_contents()が取得データを「ISO-8859-1」と認識してもデコードせずに出力する方法も見つからず。

なお、mb_detect_encoding($str, ['ASCII’, 'ISO-2022-JP’, 'UTF-8’, 'EUC-JP’, 'ISO-8859-1′,’SJIS’], true)では「UTF-8」と判定され、’UTF-8’を’ISO-8859-1’より後ろにすると「ISO-8859-1」と判定される。ただ、「ISO-8859-1」とは「ISO-8859-1エンコード」の意味なので、正しく判別できたわけではない。

従って、外部サイトからとってきたデータに応じて汎用的に文字化けを解消できる状況には至っていない。

PC