【PHP/Laravel】 CSVを読み込んだらバックスラッシュで文字化け??5c問題とCSVのimport処理

PHPのfgetcsvの欠点??特定の文字だけうまく読み込めない

ぎゅう

あれ?
特定の文字だけ\”,が出てきて、エスケープされている!!
カラムが読み込めていない….。

目次

特定の文字だけバックスラッシュが出現する

特定の文字のときだけ、\バックスラッシュが出現し、,をエスケープされてしまいます。

そうなると、1行4カラムのはずなのに、途中の行だけ3カラムしか読み込まれない問題が生まれます。

つまり、データがズレます。

こうなると、一部マスタデータが使えないので、問題になります。

このバックスラッシュが出現する問題を5c問題と言います。

5C問題とは「ソ」「表」「十」「予」などSJISの文字の2バイト目が「5C」になる文字が、fgetcsvなどの処理機に与えられたとき、それが文字の一部としてでなく、ASCIIのバックスラッシュ(5C)と判断してしまい、エスケープ文字として解釈される問題を言う。

https://qol-kk.com/wp2/blog/2020/09/10/post-1979/

引き起こす漢字は他にもあります。

— ソ Ы 噂 浬 欺 圭 構 蚕 十 申 曾 箪 貼 能 表 暴 予 禄 兔 喀 媾 彌 拿 杤 歃 濬 畚 秉 綵 臀 藹 觸 軆 鐔 饅 鷭

銀行のマスタデータだと、伊予銀行ので5C問題が発生します。

他にも店名にがつくお店もあります。

ぎゅう

パッと見ても気付けないけど、
調べてみると結構あるぞ

ぎゅう

どうやって、対処しようか?

5c問題をどう回避すればいいのか?

結論

結論、CSVのカラムを読み込む前にutf-8にファイルごと変換します。

        $contents = file_get_contents($csv);
        $utf8Contents = mb_convert_encoding($contents, 'UTF-8', 'ASCII,JIS,UTF-8,SJIS-win');

5C問題はSJISの状態で発生するので、読み込む前にUTF-8に変換してしまえば問題ありません。

よくある5C問題が発生する例

        foreach ($row as $index => $str) {
            $row[$index] = mb_convert_encoding($str, 'UTF-8', "sjis-win");
        }

または

$fp = fopen('sjis.csv', 'r');
while ($row = fgetcsv($fp) !== false) {
    // fgetcsvで読み取った後に、文字コードを変換している
    mb_convert_variables('UTF-8', 'SJIS-win', $row);
}
fclose($fp);

ほんと些細な差ですよね

行ごとにコンバートせずに、ファイルそのものをコンバートするようにしましょう😊

ぎゅう
WEBエンジニア
渋谷でWEBエンジニアとして働く。
LaravelとVue.jsをよく取り扱い、誰でも仕様が伝わるコードを書くことを得意とする。
先輩だろうがプルリクにコメントをして、リファクタしまくる仕様伝わるコード書くマン
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次
閉じる