んとぶっちゃけると「str_getcsv使うな」って感じ。
サンプルとか見てるといかにも「いけそ〜」な感じなのですが。実は「改行」を全く意識してくれないので、二次元配列を期待しているのに、ふつ〜に一次元配列でreturnしてくれやがります。
$s = "1,2,3\n4,5,6\n7,8,9\n"; $awk = str_getcsv($s); var_dump($awk);
っつわけで考えてみました。
結論からいうと「メモリ上に一時ファイル作ってからfgetcsv」がよろしげな感じ。
…っつか、str_getcsv、同じ挙動しろよ orz
「php://memory および php://temp」については、マニュアルを参照。
php.net/manual/ja/wrappers.php.php
php://memory および php://temp は読み書き可能なストリームで、一時データをファイルのように保存できるラッパーです。 両者の唯一の違いは、 php://memory が常にデータをメモリに格納するのに対して php://temp は定義済みの上限 (デフォルトは 2 MB) に達するとテンポラリファイルを使うという点です。 このテンポラリファイルの場所は、 sys_get_temp_dir() 関数と同じ方法で決めます。
php://temp のメモリ制限を制御するには /maxmemory:NN を追加します。この NN はメモリに保持するデータの最大量で、単位はバイトです。 このサイズを超えるとテンポラリファイルを使います。
微妙ではあるんだけど、一応外に向けるところに作るので、万が一を考えてphp://tempを利用。多分、/maxmemoryも指定したほうがいいんだろうなぁとか思いつつ、そこはサンプルなので、雑w
まず実験一発目。
$s = "1,2,3\n4,5,6\n7,8,9\n"; $fp = fopen('php://temp', 'r+'); fwrite($fp, $s); fseek($fp, 0, SEEK_SET); while($row = fgetcsv($fp)) { var_dump($row); }
いけるぽい。
念のために、"によるエスケープを確認。
$s = "1,2,3\n4,\"5\",6\n7,8,9\n"; $fp = fopen('php://temp', 'r+'); fwrite($fp, $s); fseek($fp, 0, SEEK_SET); while($row = fgetcsv($fp)) { var_dump($row); }
ぐっど。
次「CSVで、データとしてカンマとか改行とか」にチャレンジ。
$s = "1,2,3\n4,\"5,5.5\n5.6\",6\n7,8,9\n"; $fp = fopen('php://temp', 'r+'); fwrite($fp, $s); fseek($fp, 0, SEEK_SET); while($row = fgetcsv($fp)) { var_dump($row); }
無問題。
ある意味眼目「TSV」を確認。
$s = "1\t2\t3\n4\t5\t6\n"; $fp = fopen('php://temp', 'r+'); fwrite($fp, $s); fseek($fp, 0, SEEK_SET); while($row = fgetcsv($fp, 0, "\t")) { var_dump($row); }
いけてる。
「長さバランバラン」で「データとしてタブと改行」入り。
$s = "a\tb\t\"aa\tbb\ncc\"\nb\tb\tb\tb\tb\nc\tc"; $fp = fopen('php://temp', 'r+'); fwrite($fp, $s); fseek($fp, 0, SEEK_SET); while($row = fgetcsv($fp, 0, "\t")) { var_dump($row); }
おk。
ちなみにやっぱり面倒だからfcloseとかしてませんが、メモリ圧迫するから実務ではとっととcloseしておきませう。
ftruncateはどうなんだろう…念のために消しておきたい気もするけど、蛇足な気もする。
…こーやって、いらんTipsがまた一つ溜まっていく orz
追伸
文字コード、気をつけてね。
mb_language「ぢゃなくて」setlocaleで設定、だから。
http://d.hatena.ne.jp/gallu/20120726/p1