我正在编写一些代码来读取文件并将其分解为一系列字节的“行”段。现在我遇到了一个问题,即在大于8192字节的文件中的8192字节标记处,stream_get_meta_data()
返回unread_bytes
的{{1}}时会发生一些奇怪的行为,尽管事实上还有更多阅读,随后的阅读得到它就好了,但格式化了。
我将代码缩减为最小的例子:
0
输出:
if(count($argv) > 1 && is_file($argv[count($argv)-1])) {
if( ! $fh = fopen($argv[count($argv)-1], 'r') ) {
die('Could not open file.');
}
} else if( $fh = STDIN ) {
} else { die('No file and could not open stdin'); }
$linesize = 24; // typical line size
$bufsize = 4096; // default buffer size
$buffer = '';
$offset = 0;
$output = '';
while($buffer .= fread($fh, $bufsize)) {
$s = strlen($buffer);
for( $i=0; $i<$s; $i+=$linesize ) {
// if we're not yet at the end of the file
// if there's not enough left in the buffer for a full line
// reset the buffer to the remainder of the buffer and break to outer loop
printf("off:%d s:%d i:%d b:%d\n", $offset, $s, $i, ( $s-$i < $linesize ));
if( $s-$i < $linesize ) {
$meta = stream_get_meta_data($fh);
printf("break? unread_bytes:%d eof:%d\n", $meta['unread_bytes'], $meta['eof']);
if( $meta['unread_bytes'] !== 0 ) {
$buffer = substr($buffer, $i);
echo "broke\n";
continue 2;
}
}
// echo substr($buffer, $i, $linesize)."\n";
$offset += $linesize;
}
$buffer = '';
}
fclose($fh);
你可以看到在中间休息时,流元数据表明还有0个字节未读,但之后它会回到外部循环并再次读取。这是什么交易?
此外,我没有使用off:0 s:4096 i:0 b:0
off:24 s:4096 i:24 b:0
off:48 s:4096 i:48 b:0
[snip]
off:4032 s:4096 i:4032 b:0
off:4056 s:4096 i:4056 b:0
off:4080 s:4096 i:4080 b:1
break? unread_bytes:4096 eof:0
broke
off:4080 s:4112 i:0 b:0
off:4104 s:4112 i:24 b:0
off:4128 s:4112 i:48 b:0
[snip]
off:8136 s:4112 i:4056 b:0
off:8160 s:4112 i:4080 b:0
off:8184 s:4112 i:4104 b:1
break? unread_bytes:0 eof:0
off:8208 s:303 i:0 b:0
off:8232 s:303 i:24 b:0
off:8256 s:303 i:48 b:0
off:8280 s:303 i:72 b:0
off:8304 s:303 i:96 b:0
off:8328 s:303 i:120 b:0
off:8352 s:303 i:144 b:0
off:8376 s:303 i:168 b:0
off:8400 s:303 i:192 b:0
off:8424 s:303 i:216 b:0
off:8448 s:303 i:240 b:0
off:8472 s:303 i:264 b:0
off:8496 s:303 i:288 b:1
break? unread_bytes:0 eof:0
[actual end of file]
或feof($fh)
,因为从stdin读取时似乎没有设置,您也可以在示例中看到。
答案 0 :(得分:1)
unread_bytes
的{{3}}州:
注意:您不应在脚本中使用此值。
那就是说,看起来你要把它变得比严格必要的要复杂得多:
while (!feof($fh)) {
$line = fread($fh, $linesize);
if (strlen($line) < $linesize) {
break;
}
// do what you want
}