0
0

More than 3 years have passed since last update.

BOM 付き CSV ファイルを PHP で処理

Posted at

「phpでcsvを読み込んで項目名をキーにした連想配列をつくる[メモ]」
https://qiita.com/Terasan_Koshigaya/items/00ce0b114e527a572865
で紹介されている、csvToArray.php を使っていた。


// csvの1列目をキーにした連想配列を返す(引数:csvファイルのパス)
function csvToArray($csvPath){
  $csvArray = array();
  $firstFlg = true;
  $keys = array();
  $count = 0;
  $file = fopen($csvPath, 'r');

  while ($line = fgetcsv($file)) {
    if($firstFlg){
      for($i = 0; $i < count($line); $i++){
        array_push($keys,$line[$i]);
      }
      $firstFlg = false;
    }else{
      for($i = 0; $i < count($line); $i++){
        $csvArray[$count][$keys[$i]] = $line[$i];
      }
      $count++;
    }
  }
  fclose($file);
  return $csvArray;
}

これが、LibreOffice で出力したものは問題なかったけれども、
Excel で出力したCSVをどうもうまく読んでくれない。

以下の test1.csv (問題ない) と test2.csv ( キー名 DATE のデータが空になる ) の違いは無さそうなのだが・・・・


$ cat test1.csv
DATE,ID,NAME
2021/7/9,123,JOHN
$ cat test2.csv
DATE,ID,NAME
2021/7/9,123,JOHN


中身は同じのようなのにファイルサイズが異なっている


$ ls -alh test?.csv
-rw-r--r-- 1 www-data www-data 33  8月 31 12:00 test1.csv
-rw-r--r-- 1 www-data www-data 36  8月 31 11:59 test2.csv

改行コード CR/LF の問題かな? と思ったが、ダンプしてみると違っていた。


$ od -ax test1.csv
0000000   D   A   T   E   ,   I   D   ,   N   A   M   E  cr  nl   2   0
           4144    4554    492c    2c44    414e    454d    0a0d    3032
0000020   2   1   /   7   /   9   ,   1   2   3   ,   J   O   H   N  cr
           3132    372f    392f    312c    3332    4a2c    484f    0d4e
0000040  nl
           000a
0000041
$ od -ax test2.csv
0000000   o   ;   ?   D   A   T   E   ,   I   D   ,   N   A   M   E  cr
           bbef    44bf    5441    2c45    4449    4e2c    4d41    0d45
0000020  nl   2   0   2   1   /   7   /   9   ,   1   2   3   ,   J   O
           320a    3230    2f31    2f37    2c39    3231    2c33    4f4a
0000040   H   N  cr  nl
           4e48    0a0d
0000044

改行コードではなく、ファイル頭に efbbbf がついています。UTF-8 の BOM ですね。

このシステムは、CSVファイルをユーザーでアップロードして処理するものです。

だったのですが、 function csvToArray($csvPath) を呼び出す前に以下のように下処理をしました。

変更前:


if (is_uploaded_file($tempfile)) {
  if ( move_uploaded_file($tempfile , $filename )) {
    echo $filename . "をアップロードしました。";

変更後:


if (is_uploaded_file($tempfile)) {
  if ( move_uploaded_file($tempfile , $filename."_BOM" )) {
    exec ( "nkf -w ".$filename."_BOM > ".$filename );
    echo $filename . "をアップロードしました。";

nkf コマンドを呼び出して、-w オプションで BOM ヘッダを消去。

これでちゃんと動くようになりました。

0
0
0

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
0