fgets()は、第2引数を省略した場合、
・改行文字 (0x0A) を検出した
又は
・EOFに達した
場合に読み出しを終える。
ここに
123改行
123改行
EOF
というBOM無しファイルがあったとする。
UTF-16BEのバイト配列は
00 31 00 32 00 33 00 0A
00 31 00 32 00 33 00 0A
UTF-16LEのバイト配列は
31 00 32 00 33 00 0A 00
31 00 32 00 33 00 0A 00
となる。
このBOM無しUTF-16LEファイルを次のように読むと、
$fp = fopen("UTF16LE.txt", "r"); $bf = fgets($fp); // (1) $bf = fgets($fp); // (2)
(1)の結果は
31 00 32 00 33 00 0A
00 31 00 32 00 33 00 0A
となる。
(1) は 0x0A を検出した時点で読み出しを止め、変数 $bf へ結果を返している。
(2) は、(人から見た)1行目の「0x0A」の次の 0x00 から読み出しが開始されるため、バイトオーダーが反転した(LE からBEに変わった)ような錯覚に陥る。
そう、ここで錯覚に陥ったのがすべての始まり。
文字化けが発生しないように、マルチバイト文字列関数を使う際は必ず文字エンコードを指定するようにしているが、これは困ったことになった。
2行目以降はUTF-16BEで処理するかとか、いろいろ悩んだけど、結局
$file = file_get_contents("UTF-16LE.txt"); mb_convert_variables("UTF-16BE", "UTF-16LE", $file);
こうやってファイル全体の文字エンコードを、UTF-16BE に変換してから後の処理を行うことにした。
これね、既存のシステムから出力されるファイルを取り込んで云々の仕事をしたときの話。
0 件のコメント:
コメントを投稿