【php】file_get_contents()やブラウザで「ã«è¦è´ãã」のような文字化けがするのは、取得したデータが「utf-8」なのに「ISO-8859-1」と勘違いして「ISO-8859-1」⇒「utf-8」にデコード処理して表示しているためだった
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エンコード」の意味なので、正しく判別できたわけではない。
従って、外部サイトからとってきたデータに応じて汎用的に文字化けを解消できる状況には至っていない。