CSVの読み込みに関してファイルポインタ関連で色々と整理することがあったのでメモ。
Contents
今回やりたかった処理
- CSVファイルを読み込み(文字コードがUTF8かはわからない)
- 一時ファイルに文字コードを変換したファイルを保存
- そこから文字列を読み取る
- 一時ファイル削除
1 2 3 4 5 6 7 8 9 10 11 |
#文字コード変換 $file_contents = mb_convert_encoding($file_contents, 'UTF-8','auto'); #一時ファイル作成 $tmpfile = tempnam('/tmp', ""); #一時ファイル保存 file_put_contents($tmpfile, $file_contents); # # # ここにCSVを読み込む処理をかく #一時ファイル削除 unlink($tmpfilepath); |
結局上記の方法で落ち着きましたが、下記のような方法でも読み込めます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
$strFilePath = 'C:\\'; $strFileName = 'Test.csv'; $aryDataList = array(); //-------------------------------------------------- // 文字コードを変換した一時ファイルの作成 //-------------------------------------------------- // ファイルの読み込み $data = file_get_contents($strFilePath. $strFileName); // 文字コードの変換(UTF-8 → SJIS-win) $data = mb_convert_encoding($data, 'UTF-8', 'SJIS-win'); // 一時ファイルの作成 $temp = tmpfile(); // メタデータからファイルパスを取得して読み込み $meta = stream_get_meta_data($temp); // 一時ファイル書き込み fwrite($temp, $data); // ファイルポインタの位置を先頭に rewind($temp); //-------------------------------------------------- // ファイルの読み込み //-------------------------------------------------- // CSVファイルの読み込み $objFile = new SplFileObject($meta['uri'], 'rb'); $objFile->setFlags(SplFileObject::READ_CSV); $objFile->setCsvControl("\t", "\""); //-------------------------------------------------- // データの取得 //-------------------------------------------------- foreach ($objFile as $aryData) { $aryDataList[] = $aryData; } fclose($temp); $objFile = null; |
手法の違いとして、直接ファイルを名を指定しているか、ポインタを指定しているかだと思いますが、そこでポインタについて復習。
ファイルポインタとは
思いっきり基礎ですが、ファイルを読み込む時のメモリのアドレス。使う意図としてはより少ないメモリ、より少ない時間で処理を行うため。
処理に関してのメモ。
- tmpfileはファイル名や中身ではなく、ポインタ(ファイルのどこを読んでいるかを指し示す番地で正確にはメモリのアドレス)。
- stream_get_meta_dataはポインタを引数にして、ファイルの情報を取得することができる。今回はポインタがわかり、ファイル名がわからないケースなのでこの関数を使う。
- frwite($fp)で現在のポインタの位置(先頭からのバイト数)に書き込み
- rewind($fp)強制的にファイルポインタを先頭に戻す
ファイルポインタに関しての簡単なサンプル
https://github.com/umanari145/phptips/blob/master/filepointer/file_pointer.php