はじめに
仕事で Laravel 内でcsv を読み込むコードを作成したのでその上で知ったことに関して備忘録代わりにこちらで記載しておきます。
Shift-JIS な CSV を読み込む
windows 向けを前提とした CSV の場合、 Shift-JIS の CSV を扱うことになるかと思います。
その際、php 側は utf-8 で動いているような状態であるなら、当然ながら文字コードの変換が必要になります。
php において文字コードの変換の手法はいくつか存在しますが、保存されているファイルを読み込むような場合においては、以下の様に書くことで一行で文字コードの変換フィルターをかけたうえで読み込むことができます。
$path = '(本来のCSVファイルのパス)';
$file = new \SplFileObject('php://filter/read=convert.iconv.cp932.utf-8/resource=' . $path);
php://filter
については php 入出力ストリーム で検索をすると、read
に設定するフィルタの記法については php 変換フィルタ で検索するとより深い理解が得られます。
BOM 付き UTF-8 な CSV を読み込む
BOM 付き UTF-8 の CSV は一般的なエディタや excel で扱っている間は普通のCSVと同じように表示されますが、実際に php 上でファイルを読み込む場合には BOM を処理する必要があります。
たとえば、以下の様なデータを用意し、
id,name,age
1,"山田 太郎",34
2,"田中 花子",42
3,"佐藤 博之",51
何の処理もせずに以下の様にファイルを読みだしてみるとします。
$file = new \SplFileObject(Storage::disk('local')->path('tmp_csv/' . $privateFilename));
$file->setFlags(
\SplFileObject::READ_CSV |
\SplFileObject::SKIP_EMPTY |
\SplFileObject::READ_AHEAD
);
$header = $file->fgetcsv();
このように読み込んだ $header をログに出力してみると以下の様になります。
array (
0 => '�id',
1 => 'name',
2 => 'age',
)
内容を見てわかる通り、先頭の3バイトの BOM の記載が一緒に読み込まれることで、一つ目の文字列が余計な記載が付いた文字列として認識されます。
こちらについては単純に、以下の様に BOM を除去することで対応が可能です
$header[0] = preg_replace('/^\xEF\xBB\xBF/', '', $header[0]);
UTF-8 以外の文字コードで BOM が存在する場合、BOM となる先頭部分が UTF-8 のものとは変わりますので、扱う文字コードの BOM を確認したうえで除去を行ってください。