phpでShiftJISのcsvファイルをUTF-8で読み込む

php
スポンサーリンク

やりたいこと

phpで、ShiftJISのcsvファイルを読み込む。んで、UTF-8に出力したい

環境

  • php5.4

やり方

5C問題とは

Qiitaの記事見ると、5C問題というのがあるらしー。

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

つまり、

  1. fgetcsvで読み込む
  2. 読み込んだデータをmb_convert_variables()関数でutf-8に変換する

っていう流れで処理すると、5C問題っていうのが発生する場合があるらしく、これは避けたい。

別のファイルにUTF-8で吐き出しちゃってからfgetcsvする

こちらの記事のを使わせていただきたい。

<?php
setlocale(LC_ALL, ‘ja_JP.UTF-8’);

$file = ‘test.csv’;
$data = file_get_contents($file);
$data = mb_convert_encoding($data, ‘UTF-8’, ‘sjis-win’);
$temp = tmpfile();
$csv = array();

fwrite($temp, $data);
rewind($temp);

while (($data = fgetcsv($temp, 0, “,”)) !== FALSE) {
$csv[] = $data;
}
fclose($temp);

var_dump($csv);

ありがたやー。

  1. file_get_contents()でcsvの内容をメモリに取得
  2. mb_convert_encoding()でSjis→utf-8に変換
  3. 上記をtmpfileに書き込む
  4. 上記をfgetcsv()で読み込む

ってぇ流れですな。

さっきの、Qiitaの記事にも同じようなやり方が書いてある。
このQiitaの記事の本題である下部に記載の「ストリームフィルタ」は、今回は採用しない。今回、実装したい環境では、csvファイルが容量ちっちゃいので。なるべくシンプルにいきたい。

上記の記事のコードで個人的に特筆するところ↓↓

setlocale()

Qiita PHP「fgetcsvはsetlocaleしないと日本語が読めない」は迷信なのか? を見ると、

fgetcsvはsetlocaleしないと読めないデータがあるというのは、PHP5.3.6以下のバージョンで、PHP7の環境が普通の今日現在ではsetlocaleしなくても問題はなさそう。

っつーことなんで、PHP5.4はsetlocale()を使う必要ないニャ~。

検証ありがたいでございます~。

rewind()
PHP: rewind - Manual

rewind — ファイルポインタの位置を先頭に戻す

ほほー。

ここに書いてる例を見て、そんな動きするんだー、という感想をいだきました。

fopen()しないで良いのか?

tmpfileした場合はfopen()不要っぽい。

ちょっといじって実装

上記のを基本に、以下みたいにちょっといじって実装させていただく。

    $csv_data = file_get_contents(Config::CSV_FILE);
    $csv_data = mb_convert_encoding($csv_data, 'UTF-8', 'sjis-win');
    $temp_file = tmpfile();

    fwrite($temp_file, $csv_data);
    rewind($temp_file);

    while (($line = fgetcsv($temp_file, 0, ",")) !== FALSE) {
        // csvの1行 $line を使って処理
    }
    fclose($temp_file);

コメント