LoginSignup
0

More than 1 year has passed since last update.

【php】SplFileObjectでcsvを読み込む前に(SJIS-win → UTF-8)

Posted at

SJIS-winからUTF-8にエンコードする時は注意が必要。

before

public function convertCsv($filePath){
        $csv = new SplFileObject($filePath);
        $csv->setFlags(
            \SplFileObject::READ_CSV |           // CSV 列として行を読み込む
            \SplFileObject::READ_AHEAD |       // 先読み/巻き戻しで読み出す。
            \SplFileObject::SKIP_EMPTY |         // 空行は読み飛ばす
            \SplFileObject::DROP_NEW_LINE    // 行末の改行を読み飛ばす
        );

       $readData = collect($csv)->map(function($data,$key){
                    mb_convert_variables('UTF-8', 'SJIS-win', $data);
                    .
                    .
                    .
       }

上記の置換、SJIS-winをそのままmb_convert_variablesとすると、SJIS-win文字によっては「\」で終わることがあり、これが、置換区別後の「""」と作用して「"\"」で読み込まれて「\"」が文字認識される場合があります。

dump($data)
置換前
=> b"Ä®ô«òÈÉM,âüü[âïÆ╩Æm,ÿAîgï@ö\",https ~ "
                                  ↑これ
置換後
=> "連携機能",https:// ~ "

>> 期待値はこうでありたい
=> "連携機能",
=> "https:// ~ ",

なので、変換するときはSplFileObject読込み前に以下のように修正するとうまいこと区別して読み込んでくれます。

after

public function convertCsv($filePath){
        $fileData = file_get_contents($filePath); 
        $fileData = preg_replace("/\r\n|\r/","\n",$fileData); // 読込み行ごとの改行パターンを置換
        $encode = mb_detect_encoding($fileData, ['SJIS-win','UTF-8']); // 文字コード判定
        if($encode == 'SJIS-win'){
            $fileData = mb_convert_encoding($fileData,'UTF-8','SJIS-win'); // 区別してエンコード
        }

        $tmpName = tempnam(sys_get_temp_dir(), "csv"); 
        file_put_contents($tmpName,$fileData); // $tmpNameにファイルデータを詰めてからSplFileObjectで読込む
        $csv = new SplFileObject($tmpName);
        $csv->setFlags(
            \SplFileObject::READ_CSV |         // CSV 列として行を読み込む
            \SplFileObject::READ_AHEAD |       // 先読み/巻き戻しで読み出す。
            \SplFileObject::SKIP_EMPTY |       // 空行は読み飛ばす
            \SplFileObject::DROP_NEW_LINE      // 行末の改行を読み飛ばす
        );
        unlink($tmpName); // お掃除

        $readData = collect($csv)->map(function($data,$key){
                    return ($key !== 0) ? $this->convertItemGroup($data) : [];
                    .
                    .
                    .
                })

SplFileObjectで読み込む前に一旦、file_get_contents() で内容を取得します。
ファイルによっては改行パターンが\r\nや\rの場合があるので\nで置換します。
あとはエンコードすると、「\"」問題は解消されました。

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
0