やりたいこと
phpで、ShiftJISのcsvファイルを読み込む。んで、UTF-8に出力したい
環境
- php5.4
やり方
5C問題とは
Qiitaの記事見ると、5C問題というのがあるらしー。
5C問題とは、「ソ」「表」「十」「予」などSJISの文字の2バイト目が「5C」になる文字が、fgetcsvなどの処理機に与えられたとき、それが文字の一部としてでなく、ASCIIのバックスラッシュ(5C)と判断してしまい、エスケープ文字として解釈される問題
つまり、
- fgetcsvで読み込む
- 読み込んだデータを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);
ありがたやー。
- file_get_contents()でcsvの内容をメモリに取得
- mb_convert_encoding()でSjis→utf-8に変換
- 上記をtmpfileに書き込む
- 上記をfgetcsv()で読み込む
ってぇ流れですな。
さっきの、Qiitaの記事にも同じようなやり方が書いてある。
このQiitaの記事の本題である下部に記載の「ストリームフィルタ」は、今回は採用しない。今回、実装したい環境では、csvファイルが容量ちっちゃいので。なるべくシンプルにいきたい。
上記の記事のコードで個人的に特筆するところ↓↓
setlocale()
Qiita PHP「fgetcsvはsetlocaleしないと日本語が読めない」は迷信なのか? を見ると、
fgetcsvはsetlocaleしないと読めないデータがあるというのは、PHP5.3.6以下のバージョンで、PHP7の環境が普通の今日現在ではsetlocaleしなくても問題はなさそう。
っつーことなんで、PHP5.4はsetlocale()を使う必要ないニャ~。
検証ありがたいでございます~。
rewind()
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);
コメント