とぎぷろべい

包丁研ぎとプログラミングと米国株投資についてのなんやかんや

CSVファイルの読み込みと書き出しについて(PHP)

f:id:feci:20210727001932j:plain

PHP7

 

PHP7.4.1におけるCSVファイルの読み込みと書き出しについて

 

CSVデータを作成する用のPHPファイル。

<?php

$aa = [
  ['うどん'600],  //CSVデータ化する内容
  ['そば'500],    //CSVデータ化する内容
];

$file = new SplFileObject('aaa/aa.csv''w');  //SplFileObjectクラスを使って$aaのデータをCSVデータ化

foreach ($aa as $a) {  //$aaの配列データを1つずつ$aに入れてループ処理
  $file->fputcsv($a);  //fputcsvメソッドでフィールドの配列データをCSVの行としてファイルに書き出す
}

 

上記PHPファイルの実行によって作成されたCSVファイル。

うどん,600
そば,500

 

CSVファイルはカンマで値を区切ったデータが入っているファイルのことです。

 

CSVはComma Separated Valueの略です。

CSVの名称のとおり、このファイルはカンマ(comma)で区切った(separated)値(value)を管理するためのファイルです。

 

なのでCSVファイルは「カンマ区切りファイル」とも言うらしいです。

CSVファイルの拡張子は.csvです。

 

 

上記スクリプトのようにSplFileObjectクラスのインスタンス作成時にパラメータに (フォルダ名/CSVデータを書き込みたいファイル名, 'オープンモードの指定'); をそれぞれ記述することで、指定したCSVファイルに任意のCSVデータを書き込むことが可能になります。

 

CSVデータをあつかう場合は、ほとんどが配列データになるかと思います。

なので今回も、データは「うどん」と「そば」の2つしかありませんが、foreach文を使って配列データをCSVデータ化して指定したCSVファイルに書き込んでいます。

 

foreach文のブレイス(波括弧)の中に  SplFileObjectクラスのインスタンス名->fputcsv(CSVデータ化したい変数名); を記述することで、コンストラクターで指定したCSVファイル内にfputcsvメソッドのパラメータに指定したデータがCSVデータとして書き込まれます。

 

fputcsvメソッドは、フィールドの配列をCSVの行として書き出す処理をおこなうSplFileObjectクラスのメソッドです。

ちなみにフィールドとはメンバ変数のことです。

 

しかしこの場合は$aaはクラス外で宣言している変数なのでこれがメンバ変数なのかと言われるとちょっと違うような気もします。

でもPHPの公式H.P.の説明にはっきりとフィールドと書いていたので、まあなんかこれもフィールドらしいです。

 

 

CSVファイルのデータの読み込みについて。

<?php

$a = new SplFileObject('aaa/aa.csv'); //SplFileObjectクラスのインスタンスの作成

//①推奨される記述
while (!$a->eof()) {   //$a->eof()===falseの条件を満たす場合に下行の処理を実行
  $aa = $a->fgetcsv(); //fgetcsvメソッドでaaa.csvから取り出したデータを$aaに代入
  echo $aa[0], "\n";   //現在の$aaのindex0番目に入っている値を出力
}

$a->setFlags(SplFileObject::READ_CSV); //インスタンスにREAD_CSVフラグを建てる

//②推奨されないフラグを使った記述
foreach ($a as $b) { //READ_CSVフラグが建っていると$aが勝手にaa,csvのデータを読み込む
  echo $b[1], "\n";  //現在の$aaのindex0番目に入っている値を出力
}

CSVファイルのデータを読み込むには2つの方法があります。

 

1つはfgetcsv関数を使ってオブジェクト指向の記述でデータを読み込む方法です。

もう1つは、インスタンスからSplFileObjectクラスのREAD_CSVフラグをセットして自動でデータを読み込ませる方法です。

 

たとえば、上記スクリプトで読み込んでいるaa.csvが以下のような内容だったとします。

うどン,600
そば,500
ラーメン,550

そのうえで上記のスクリプトを実行すると、$aaまたは$bには次のような値が代入されます。

 

 

〇$aa[0]または$b[0]の値

うどン
そば
ラーメン

 

〇$aa[1]または$b[1]の値

600
500
550

 

 

上記のような配列の形でCSVデータが変数に代入されます。

 

またSplFileObjectのフラグをセットするには、setFlagsメソッドを使います。

SplFileObjectクラスに使えるフラグの一覧は以下のとおりです。

 

 

DROP_NEW_LINE

行末の改行を読み飛ばします。

 

・READ_AHEAD

先読みまたは巻き戻しでCSVデータを読み出します。

 

・SKIP_EMPTY
ファイルの空行を読み飛ばします。

このフラグはREAD_AHEADフラグが有効になっていない状態だと挙動がおかしくなるらしいです。

 

・READ_CSV
CSV列として行を読み込みます。

 

 

〇なぜ「うどん」ではなく「うどン」なのか

上記の内容の補足として、なぜCSVファイルに「うどん,600」ではなく「うどン,600」と記述しているのかについて説明します。

 

私の環境ではなぜか、CSVデータのstr型文字列の末尾の値を平仮名の「ん」にすると、PHPファイルに読み込んだデータがバグります。

理由は不明なのですが、どんな文字列であっても末尾を平仮名の「ん」にした瞬間に、どのデータも同様にバグります。

 

どのようにバグるのかというと、「うどん,600」にすると以下のようにバグります。

 

 

〇$aa[0]または$b[0]の値

うどん,600

 

〇$aa[1]または$b[1]の値

PHP Notice:  Undefined offset: 1 in C:\MAMP\htdocs\php\…
    ← 空行

 

 

なぜこのような挙動になるのかは、現在プロの人に問い合わせ中です。

原因が分かったら追加でそれについて書こうと思いますが、たぶん分からないんじゃないかと思います。

 

ITってそういうもんですよね。

 

 

以上です。