我来自C和C++背景,但也玩一些网络的东西.所有的美国C乡亲(希望)知道,叫feof上FILE*做一个读之前是一个错误.这是经常咒骂C和C++新手的东西.这也是PHP实现的情况吗?
我认为它必须是因为文件可能是一个套接字或其他任何在完成阅读之前无法知道大小的东西.但几乎每个PHP示例(即使是在我看过的php.net上发现的那些看起来像这样(并且警报在我脑海中消失):
$f = fopen("whatever.txt", "rb");
while(!feof($f)) {
echo fgets($f);
}
fclose($f);
Run Code Online (Sandbox Code Playgroud)
我知道最好像这样写这个并避免这个问题:
$f = fopen("whatever.txt", "rb");
while($line = fgets($f)) {
echo $line;
}
fclose($f);
Run Code Online (Sandbox Code Playgroud)
但这是重点.我试过测试如果我以"错误的方式"做错事情就会失败,但我无法让它导致不正确的行为.这不完全科学,但我认为值得一试.
那么,在PHP feof之前调用是不正确的fread?
有几种方法可以让PHP以不同的方式完成C的版本,但我觉得它们有缺点.
他们可以默认为!EOF.这是次优的,因为对于某些角落情况可能不正确.
他们可以在fopen调用期间获取文件大小,但这不适用于所有类型的文件资源,会产生不一致的行为并且速度会变慢.
在您尝试读取文件之前,PHP 并不知道它是否位于文件末尾。试试这个简单的例子:
<?php
$fp = fopen("/dev/null","rb");
while (!feof($fp)) {
$data = fread($fp, 1);
echo "read " . strlen($data) . " bytes";
}
fclose($fp);
?>
Run Code Online (Sandbox Code Playgroud)
您将得到一行读数read 0 bytes。feof() 返回 true,即使您在技术上位于文件末尾。通常这不会导致问题,因为fread($fp, 1)不返回任何数据,并且您正在执行的任何处理都不会很好地处理任何数据。如果您确实需要知道是否位于文件末尾,则必须先进行读取。