8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

容量の大きいCSVファイルの扱い (Shift-JIS)

Last updated at Posted at 2021-06-02

概要

大きなCSVファイルを扱う際に、調べたことをメモしておく。

文字コード問題

CSVファイルは、だいたいShift-JISのエンコードで渡されてくることが多いです。
そのため、文字コードをUTF8に変換するなどの処理が必要になったりします。

しかし、Shift-JISのエンコードには、「5C問題」というものがあるようです。
5C問題

そのため、shift-jisエンコードのCSVファイルをそのまま扱おうとすると問題が発生します。

例)下記のようなCSVの行が合った場合、「ソ」がC5問題に引っかかります
"ほげ","ミソ","1","2"

   ↓↓↓ ※「ソ」の後の「"」がエスケープされる

"ほげ","ミソ\",\"1","2"  ( 行がずれる... )

エンコード変換

CSVパーズする前に文字コードを変換する。

下記のようにエンコード変換したファイルを作成してみました。

$str = file_get_contents('sjis.csv');
$str = mb_convert_encoding($str, 'UTF-8', 'ASCII,JIS,UTF-8,SJIS-win');
file_put_contents('utf8.csv', $str);

しかし、このやり方だと、CSVファイルの容量が大きくなるとPHPの消費メモリーが増えます。

そのため、頻繁にメモリーオーバーのエラーを起こします。

Allowed memory size of 536870912 bytes exhausted (tried to allocate 483345347 bytes)

このやり方は、駄目でした...

対応方法

fopenでもSplFileObjectなどで、1行ごと読んで処理する方式だと、メモリーの消費を抑えられそう。

そこで、「 SplFileObject 」を使いました。
( ただし、CSVとしてパーズせず、1行ごとにエンコード変換するようにする )

DB::beginTransaction();
try {
    // ファイルの読み込み
    $file = new SplFileObject($file);
    $file->setFlags(
        // SplFileObjectでCSVパーズしない (Shift-JISの5C問題)
        // SplFileObject::READ_CSV |  // CSV解析(パーズ)する
        SplFileObject::READ_AHEAD |   // 先読み/巻き戻しで読み出す
        SplFileObject::SKIP_EMPTY |   // 空行は読み飛ばす
        SplFileObject::DROP_NEW_LINE  // 行末の改行を読み飛ばす
    );

    foreach ($file as $line) {
        // 文字エンコード変換
        // ※ Shift-JISの5C問題があるため、CSVパーズ前にエンコードを変換する
        $line = mb_convert_encoding($line, 'UTF-8', 'ASCII, JIS, UTF-8, SJIS-win');
        $row = str_getcsv($line);

        // 何かしら処理を実装する

        DB::commit();
    }
} catch (Exception $e) {
    DB::rollback();

    // Laravelのエラーハンドリングに渡すため、スローする
    // Throw to pass to error handling of Laravel.
    throw $e;
}

とりあえず、このやり方で、30万件のデータの処理ができました。

fgetcsv関数のストリームフィルタでも対応できそうですが、実装が複雑になりそうだったので断念。

文字コードの問題は、毎回面倒になりますね(^^;)

参考サイト

以上

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?