ラボ > PHP:ファイル関連

CSVファイルの読込み前に文字コード変換(SplFileObject())

CSVファイルには何万件もレコードがある。しかもSHIFT-JIS。どうにかしたいとき。

作成日:2018-11-09, 更新日:2018-11-09

基本

・文字コードを変換して一時ファイルに保存
・一時ファイルをSplFileObject()にいれて使う
って方法がある。

▼コード

$filPath = 〇〇〇〇;
$data = @file_get_contents($filPath);

// 文字コードの変換(UTF-8 → SJIS-win)
$convertData = mb_convert_encoding($data, 'UTF-8', 'SJIS-win');

// 一時ファイルの作成
$temp = tmpfile();
$meta = stream_get_meta_data($temp);

// 変換してデータを一時ファイルに書き込む
fwrite($temp, $convertData);

// ファイルポインタの位置変更
rewind($temp);

$objFile = new SplFileObject($meta['uri']);
~略~
foreach ( $objFile as $rowData ) {
  ~略~
}

fclose($temp);

こんな感じのソースにしろという人が多いけど、気になるのが最初の「file_get_contents()」。
・・・ファイル容量が大きいときにココで落ちそうな気がする・・・。

ファイル容量が大きいときの対策

元のファイルをUTF-8にしてもらう

これが全てのような気がする。

linux(?)で変換をかける

試しておらず・・・メモ程度。

1.PHPの「exec()、system()」などで、linuxの「iconv」のコマンドで文字コードの変換をかける
2.変換をかけたファイルで「SplFileObject()」を使う
※「nkf」のコマンドでもいけるけど・・・インストされているかチェックが必要。

懸念点

・「iconv」で文字コードの変換をかけると新たにファイルができる
→あとで削除させる処理が必要

・元の文字コードの調べ方(linuxで「file -i ファイル」)を使えば、調べることは可能。
→「charset=unknown-8bit」と出てきた場合・・・多分「SHIFT-JIS」だと思うけど確証は無い

・そもそも「iconv」の変換でメモリ不足が起きないという保証がない。
→大容量のファイルで試せば分かるけど・・・未調査。

・「iconv」で「SJIS-WIN」が使えるのか?、「SHIFT_JIS」で対応してくれているのか?
→未調査

関連項目

PHPでCSV(or TSV)ファイルの読み込み(SplFileObject())
PHP ファイルから各行を取得して何かしたい(SplFileObject())、LimitIterator())