SJISなCSVを読み込む手法
CSVを読み込むためにPHPではfgetcsvという便利な関数が用意されている。だけどPHPで使用できる文字コードの関係で、CSVファイルがシフトJISな場合はデータが破損してしまうことがある。普通なら「文字コードを変換すれば」ということになるが、fgetcsv関数はファイルポインタを引数としてとるため、一旦文字コード変換した内容を一時ファイルに書き出してやらなければならない。しかしこれはスマートでない。また、実はPHPにはそれさえも考慮したstr_getcsv関数があるらしい。こちらは引数として文字列を与えることができる!。しかしこの関数、どうもCVSバージョンだけに存在するらしく、たいていの場合この関数を使用できる環境ではなさそうだ。
実は便利な手法があった。ファイルとして書き出すのではなく「いったんメモリに保存する」というなんともおしゃれな手法だ。やり方としてはこんな感じ。
$text=file_get_contents($filePath);
$text=mb_convert_encoding($text,’UTF-8′,’SJIS’);
$fp=fopen(‘php://temp’,’r+’);
fwrite($fp,$text);
rewind($fp);
while($values=fgetcsv($fp,1024)){
var_dump($values);
}
3行目がおしゃれ。php://tempとすることでメモリに書き出してくれるらしい。しかも容量を考慮して、容量が大きい場合はファイルに書き出してくれたりもする(たぶん一時ファイルとして書き出して処理完了後は消えてくれるんだろうと期待するわけだが)。この行が魅力的なのはr+でオープンしているところ。それは5行目を見れば理解できる。
もう一個ミソが5行目。書き出したファイルを一旦クローズして、再度オープンするなんてことはしない。rewind関数でファイルポインタを最初に戻してやるわけだ。ここでr+オープンした意味が出てくる。書き出しておいて、読み直すわけだ。
すごくかっこいい。多用しそう。でも「php://temp」はPHP5.1という条件付。入出力ストリームは使う機会こそ少ないけれど、要所要所で重要になる使い方だとしみじみ思う次第であった。