ハマる定番みたいな事象なんですが、なかなか解決出来ずに小一時間あれこれ試しました。
環境は Windows 7 pro 64bit上で動く XAMPP 1.7.5 beta1 です。 Apache、PHP(MySQLも)の文字コードは UTF-8 にしています。
読み込むCSVファイルは、社内の購買システムが吐き出した購買実績で、ダブルクオーテーションは使わずカンマで区切っただけのシフトJISエンコーディングされたファイルです。
最初に見つけたのは「PHPのお勉強」さんの例。 読み込めましたが、文字化けします。 ページのエンコードをシフトJISにすると見えるようになりますが、先頭の日本語が化けたままです。
「phpを勉強してみる」さんの事例は、fgetcsvのマニュアルに記載された例題に近いですが、やっぱり同じ状況ですね。 「Webにまつわるエトセトラ」さんのやり方も同様です。
「php csv 先頭 文字化け」でぐぐったら、「PHPプロ!」さんにそのものズバリの質問があって、yossyさんの fgetcsv_reg を見つけることが出来ました。 これで解決できました。
ただ使い方の例の中で
mb_convert_variables($_enc_to,$_enc_from,$data);
となっている部分は、
mb_convert_variables('UTF-8', 'sjis-win', $data);
に変更しました。 最初は「sjis」としていたんですが、CSVファイルに機種依存文字が含まれていたので、「sjis-win」としました。
その後、の「日本語の先頭が化ける」原因について、「Pentan.info」さんの解説から、CSVファイルを読み込む前に、
setlocale(LC_ALL, 'ja_JP.UTF-8');
を実行すればよいということがわかりました。 これで、fgetcsv_reg を使わなくても「PHPのお勉強」さんのやり方で化けなくなりました。 こちらの方が処理が速いです。
CSVファイルの読み込み方法の違いによる処理速度の比較では「130単位」さんの記事が興味深いです。 「PHPのテクメモ」さんの方法も試してみましたが、今までと違う部分で文字化けします。 なんでだろ?
他にもCSVファイルを読み込む際の注意点は「Asial blog」さんの記事が参考になりました。
今回はそれほどサイズの大きなファイルではありませんでしたが、今後「hnwの日記」さんのような方法も必要になってくるかもしれません。
先人の知恵に感謝です。
その後、購買システムから新たにCSVファイルをダウンロードしたら、今度はダブルクオーテーションで囲まれてました。 仕様変更されたのかな?
fgetcsv には、ダブルクオーテーションを取り除く機能があるので便利ですね。