Windows版php-7.1 で UTF8 の CSV をパースする
Windows版PHP(xampp) の fgetcsv() が、php-5.6 と php-7.1 で挙動が変わったことがわかった。
たぶん php-7.0 から。
fgetcsv() はlocaleに依存する関数なので、
UTF8のCSVを読み込むなら ja_JP.UTF-8
を指定する必要があるとマニュアルにもあるのだけど、
Windowsではそもそも UTF-8 ロケールを指定できない。
php-5.6 では特に何も指定せず、デフォルトの Japanese_Japan.932
のままでもUTF8のファイルを読み込めていた・・たぶん。
手元の開発環境でしかないから、テストケースが少なかった可能性はあるけども。
ともかく挙動は変わっている。
php7以降では、Windowsの場合は C ロケールを設定する必要がある模様。
挙動が違う例
<?php $strCsv = '"サーロイン","カルビ","リブロース"'; $fp = fopen('php://memory', 'wb'); fputs($fp, $strCsv); rewind($fp); $arrCsv = fgetcsv($fp); fclose($fp); var_dump($arrCsv);
実行結果(php-5.6.8 xampp)
array(3) { [0] => string(15) "サーロイン" [1] => string(9) "カルビ" [2] => string(15) "リブロース" }
実行結果(php-7.1.1 xampp)
array(2) { [0] => string(15) "サーロイン" [1] => string(27) "カルビ",リブロース"" }
対応策
UTF8 ロケールがないからどうしようと思ったけど、C ロケールにしたらうまくいった模様。
テストケースはこの3枚の肉だけだけども。
<?php // php7だとこれが必要ぽい if(0 === strpos(PHP_OS, 'WIN')) { setlocale(LC_CTYPE, 'C'); } var_dump(setlocale(LC_ALL, 0)); $strCsv = '"サーロイン","カルビ","リブロース"'; $fp = fopen('php://memory', 'wb'); fputs($fp, $strCsv); rewind($fp); $arrCsv = fgetcsv($fp); fclose($fp); var_dump($arrCsv);
LC_CTYPE | php5.6 | php7.1 |
---|---|---|
Japanese_Japan.932 (default) | ○ | × |
C | ○ | ○ |