PHPのSplFileObjectでURLを指定してCSVを読み込む

シェアする

  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存

URLをSplFileObjectで使うにはNoRewindIteratorクラスも一緒に使う


$url = 'http://sample.com/data.csv'; //オンライン上のCSVファイル
$file = new NoRewindIterator( new SplFileObject( $url ));
$file->setFlags( SplFileObject::READ_CSV );
foreach ( $file as $line ) {
$results[] = $line;
}
var_dump( $results );

所感

PHPでCSVファイルを読み込んで配列に入れるなど、最近は「SplFileObject::READ_CSV」を使った方が早いという情報が増えてきています。


$path_file = "./sample.csv"; //ローカル上のCSVファイル
$file = new SplFileObject( $path_file );
$file->setFlags( SplFileObject::READ_CSV );
foreach ( $file as $line ) {
    $results[] = $line;
}
var_dump( $results );

確かに早い気がするのですが、オブジェクトを生成する際の引数にURLを使うと下記のようなエラーが発生します。

Warning: SplFileObject::rewind(): stream does not support seeking in /xxxx/xxxx/get_json.php on line xx

Fatal error: Uncaught exception ‘RuntimeException’ with message ‘Cannot rewind file https://xxxx/xxxx.csv’ in /xxxx/xxxx/get_json.php:xx
Stack trace: #0 /xxxx/xxxx/get_json.php(xx):
SplFileObject->rewind() #1 {main} thrown in /xxxx/xxxx/get_json.php on line xx

しかし、公式のマニュアルには下記のようにオブジェクト作成時の引数にファイル名の代わりにURLは使えると書かれています。

ヒント
fopen wrappers が有効の場合、この関数のファイル名として URL を使用することができます。ファイル名の指定方法に関する詳細は fopen() を参照ください。 サポートするプロトコル/ラッパー には、さまざまなラッパーの機能やその使用法、 提供される定義済み変数などの情報がまとめられています。

「使える」とあるのに使えない理由は、SplFileObjectクラスは面倒な繰り返し処理をクラス化したイテレータの1つであるためです。

SplFileObjectクラスはSPL(Standard PHP Library)というPHPの標準ライブラリのうちファイル操作用のイテレータです。つまり、基本的にファイルを開き、1行ずつ処理することが前提です。そのため、rewind()というメソッドでファイルのポインタを先頭に戻しながら処理していくのですが、スキーム付きのファイル名(”http://〜”や”php://〜”や”ftp://〜)の場合はストリームとなるため(区切りがわからず)行ごとの処理ができません。つまり、このrewind()処理の時にポインタを先頭に戻せないためエラーが発生します。

そこで、rewind処理をさせないためにrewindできないNoRewindIteratorクラスにSplFileObjectクラスのインスタンスを渡して処理させます。

イテレータに関してhnwさんの記事が大変参考になったので、一読をおすすめします。

参考文献


スポンサーリンク
レクタングル(大)広告

シェアする

  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存
スポンサーリンク
レクタングル(大)広告