回答編集履歴
7
NoRewindIteratorは内側じゃないとダメっぽい
test
CHANGED
@@ -34,9 +34,13 @@
|
|
34
34
|
|
35
35
|
|
36
36
|
|
37
|
+
// Rewindされないようにラップする
|
38
|
+
|
39
|
+
$it = new NoRewindIterator($file);
|
40
|
+
|
37
41
|
// 空行を読み飛ばすようにラップする
|
38
42
|
|
39
|
-
$it = new CallbackFilterIterator($
|
43
|
+
$it = new CallbackFilterIterator($it, function ($row) { return $row !== [null]; });
|
40
44
|
|
41
45
|
// $pオフセットから$e件に制限するようにラップする
|
42
46
|
|
@@ -44,9 +48,9 @@
|
|
44
48
|
|
45
49
|
|
46
50
|
|
47
|
-
//
|
51
|
+
// 配列に変換
|
48
52
|
|
49
|
-
$records = iterator_to_array(
|
53
|
+
$records = iterator_to_array($it);
|
50
54
|
|
51
55
|
|
52
56
|
|
6
もうちょいシンプルに
test
CHANGED
@@ -38,19 +38,15 @@
|
|
38
38
|
|
39
39
|
$it = new CallbackFilterIterator($file, function ($row) { return $row !== [null]; });
|
40
40
|
|
41
|
-
// rewindさせないようにラップする
|
42
|
-
|
43
|
-
$it = new NoRewindIterator($it);
|
44
|
-
|
45
41
|
// $pオフセットから$e件に制限するようにラップする
|
46
42
|
|
47
43
|
$it = new LimitIterator($it, $p, $e);
|
48
44
|
|
49
45
|
|
50
46
|
|
51
|
-
// 配列に変換
|
47
|
+
// rewindを防ぎながら配列に変換
|
52
48
|
|
53
|
-
$records = iterator_to_array($it);
|
49
|
+
$records = iterator_to_array(new NoRewindIterator($it));
|
54
50
|
|
55
51
|
|
56
52
|
|
5
バグ修正 \(File::READ_AHEADおよびFile::SKIP_EMPTYはHTTP URLに対しては使えない模様\)
test
CHANGED
@@ -28,21 +28,29 @@
|
|
28
28
|
|
29
29
|
$file = new File('http://example.com/ttt.txt', 'rb');
|
30
30
|
|
31
|
-
$file->setFlags(File::READ_CSV | File::
|
31
|
+
$file->setFlags(File::READ_CSV | File::DROP_NEW_LINE); // CSVモード (但し空行読み飛ばしモードは使えない)
|
32
32
|
|
33
33
|
$file->setCsvControl("\t"); // セパレータをタブ文字に
|
34
34
|
|
35
35
|
|
36
36
|
|
37
|
-
//
|
37
|
+
// 空行を読み飛ばすようにラップする
|
38
38
|
|
39
|
-
|
39
|
+
$it = new CallbackFilterIterator($file, function ($row) { return $row !== [null]; });
|
40
40
|
|
41
|
-
//
|
41
|
+
// rewindさせないようにラップする
|
42
42
|
|
43
|
-
|
43
|
+
$it = new NoRewindIterator($it);
|
44
44
|
|
45
|
+
// $pオフセットから$e件に制限するようにラップする
|
46
|
+
|
45
|
-
$
|
47
|
+
$it = new LimitIterator($it, $p, $e);
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
// 配列に変換
|
52
|
+
|
53
|
+
$records = iterator_to_array($it);
|
46
54
|
|
47
55
|
|
48
56
|
|
4
蛇足
test
CHANGED
@@ -112,4 +112,8 @@
|
|
112
112
|
|
113
113
|
|
114
114
|
|
115
|
-
上記を満たす場合,一時的な配列を生成する必要すらありません。イテレータのまま
|
115
|
+
上記を満たす場合,一時的な配列を生成する必要すらありません。イテレータのまま`foreach`で回してもらって構いません。ただし条件を満たしていないのにやってしまうと,`foreach`ループ中に通信障害が発生したときにHTMLが中途半端な状態でぶっ壊れて出力されてしまうので注意。
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
一度配列を作る意味としては,「一度作ってしまえば配列は絶対に壊れることが無い」と保証できるからですね。HTTP経由でURLをオープンしているイテレータは不安定なことを意識しなければなりません。
|
3
蛇足
test
CHANGED
@@ -99,3 +99,17 @@
|
|
99
99
|
</ul>
|
100
100
|
|
101
101
|
```
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
蛇足ですが,
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
- [ob_start](http://php.net/manual/ja/function.ob-start.php)を使って出力HTMLのバッファリングを行っている
|
110
|
+
|
111
|
+
- エラーや例外が発生したときには正常系で使うHTMLのバッファを破棄してエラー用のHTMLに切り替える処理を書いている
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
上記を満たす場合,一時的な配列を生成する必要すらありません。イテレータのままそのまま`foreach`で回してもらって構いません。(条件を満たしていないのにやってしまうと,`foreach`ループ中に通信障害が発生したときにHTMLが中途半端な状態でぶっ壊れて出力されてしまうので注意)
|
2
LimitIterator使ったほうがよさそう
test
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
[
|
1
|
+
[NoRewindIterator](http://php.net/manual/ja/class.norewinditerator.php) なんてあったんですね,勉強になりました。不可逆なストリームを扱う際には必須ですね。
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
あと調べていたら[LimitIterator](http://php.net/manual/ja/class.limititerator.php)なるものもあるようです!一度全部配列に変換してから切り取るよりも,部分的にイテレータの段階で読み捨てを行ったほうがメモリ効率が圧倒的にいいので是非こちらで。
|
2
6
|
|
3
7
|
|
4
8
|
|
@@ -30,11 +34,15 @@
|
|
30
34
|
|
31
35
|
|
32
36
|
|
33
|
-
// イテレータ
|
37
|
+
// SplFileObjectはイテレータでもあるが,iterator_to_array適用時に
|
34
38
|
|
35
|
-
//
|
39
|
+
// rewind処理が発生してしまうのでNoRewindIteratorでラップする。
|
36
40
|
|
41
|
+
// 更に,必要な部分だけを効率的に残せるLimitIteratorでラップする。
|
42
|
+
|
43
|
+
// 最後に配列に変換する。
|
44
|
+
|
37
|
-
$records =
|
45
|
+
$records = iterator_to_array(new LimitIterator(new NoRewindIterator($file), $p, $e));
|
38
46
|
|
39
47
|
|
40
48
|
|
1
シングルクオート派
test
CHANGED
@@ -22,7 +22,7 @@
|
|
22
22
|
|
23
23
|
// SplFileObjectでURLをオープンする
|
24
24
|
|
25
|
-
$file = new File(
|
25
|
+
$file = new File('http://example.com/ttt.txt', 'rb');
|
26
26
|
|
27
27
|
$file->setFlags(File::READ_CSV | File::SKIP_EMPTY | File::READ_AHEAD | File::DROP_NEW_LINE); // CSVモード
|
28
28
|
|