裏紙に書く程度の内容

SplFileObject で全角文字が扱えない場合の対処法

PHP の SplFileObjectでcsvファイルを読み込むと、マルチバイト(全角)文字が含まれているデータがうまく読み込まれません。

その場合の対処法メモ。

事象

たとえば以下のようなcsvファイルを読み込むものとします。

data1\tテスト\t1行目
data2\tテストテ\t2行目
data3\tテストテス\t3行目
data4\tテストテスト\t4行目

\tの箇所がタブ。

これをSplFileObjectで読み込みます。

$file = new SplFileObject('test.csv');
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl("\t");

foreach ($file as $line) {
    var_dump($line);
}

すると、結果はこう。

array(2) {
  [0]=>
  string(5) "data1"
  [1]=>
  string(17) "テスト       1行目"
}
array(3) {
  [0]=>
  string(5) "data2"
  [1]=>
  string(12) "テストテ"
  [2]=>
  string(7) "2行目"
}
array(3) {
  [0]=>
  string(5) "data3"
  [1]=>
  string(15) "テストテス"
  [2]=>
  string(7) "3行目"
}
array(2) {
  [0]=>
  string(5) "data4"
  [1]=>
  string(26) "テストテスト    4行目"
}

2,3行目はうまくいってますが、1,4行目がおかしい。\t(タブ)がカラムデータとして読み込まれてしまっています。

windows上のphpでのみ、上記のような結果になります。

これが仕様なのか windows版phpのバグなのかよくわかりませんが(windows上でだけNGなのでバグっぽいですが)。

対処方法

原因はいまいちよくわかりませんでしたが、とりあえず以下でうまくいっています。

setlocale(LC_CTYPE, 'C');
$file = new SplFileObject('test.csv');
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl("\t");

foreach ($file as $line) {
    var_dump($line);
}

setlocale()LC_CTYPE'C'に変更するだけ。

Index