PHP的feof行为与C的行为有何不同?

6
我来自C和C++背景,但也涉猎一些Web技术。所有的C程序员(希望如此)都知道在读取之前调用feof是一个错误。这是初学者在C和C++中经常遇到的问题。PHP的实现是否也是如此?我认为一定是的,因为文件可能是套接字或其他任何不可能在完成读取之前知道大小的东西。但几乎所有的PHP示例(即使是在php.net上找到的示例)看起来都像这样(我的警报响了):
$f = fopen("whatever.txt", "rb");
while(!feof($f)) {
    echo fgets($f);
}
fclose($f);

我知道最好这样写以避免这个问题:

$f = fopen("whatever.txt", "rb");
while($line = fgets($f)) {
    echo $line;
}
fclose($f);

但这不是重点。我试图测试如果我用“错误的方法”做会有什么失败,但我无法导致不正确的行为。这不是非常科学,但我认为值得一试。

那么,在 PHP 中在 fread 之前调用 feof 是不正确的吗?

PHP 可以有几种不同于 C 的方式来处理这个问题,但我觉得它们都有缺点。

  • 他们可以将默认值设置为 !EOF。这是次优的,因为它可能对某些特殊情况不正确。

  • 他们可以在 fopen 调用期间获取文件大小,但这不能在所有类型的文件资源上工作,导致不一致的行为并且会更慢。

3个回答

3

在读取文件之前,PHP不知道它是否已经到达文件的末尾。请尝试这个简单的例子:

<?php 
$fp = fopen("/dev/null","rb"); 
while (!feof($fp)) { 
    $data = fread($fp, 1);
    echo "read " . strlen($data) . " bytes";  
} 
fclose($fp); 
?>

您将得到一行读取“read 0 bytes”的信息。即使您技术上已经到了文件的结尾,feof()函数也会返回true。通常这不会导致问题,因为fread($fp, 1)不会返回任何数据,并且您对无数据进行处理的任何处理都可以正常运行。如果您确实需要知道是否已到达文件结尾,则必须先进行一次读取。

0
这可能更像是一个问题而不是答案,但为什么不使用 file_get_contents() 呢?在我的经验中,如果您正在读取文件或流,此函数将为您完成繁重工作(假设您想将整个资源读取为字符串,或者知道/可以计算限制和偏移量)。它的姊妹函数 file_put_contents() 反向运行良好。
例如,这里是一个例子:
$expected_content = "Hello Stack Overflow!"
$real_content = file_get_contents("/path/to/file.txt");
if ($expected_content != $real_content){
   file_put_contents("/path/to/file.txt", $real_content);
}

或者一个流:

$expected_content = "Hello Stack Overflow!"
$real_content = file_get_contents("http://host.domain.com/file.txt");
if ($expected_content != $real_content){
   $options = array('ftp' => array('overwrite' => true));
   $stream = stream_context_create($options); 
   file_put_contents("ftp://user:pass@host.domain.com/file.txt", $real_content, 0, $stream);
}

那么你就不必担心EOF或其他任何事情,这些都将为您完成(ftp put有点棘手,但没关系)。当然,这并不适用于所有情况...

我是否错过了原始问题中使此方法不可行的内容?


1
你的方法很好,完全合理,我的问题更多是学术性的而非实际性的。我只是想知道在PHP中的foef是否与C中的行为相同。谢谢。 - Evan Teran
1
啊,一个学者,我没看到你的带有粗花呢肘部的皮夹克8o)(霍默·辛普森赢了,“更正,我毁了两件夹克!”) - TCCV

-1

你所说的在调用fread之前不需要调用feof的断言是不正确的-因此问题是无效的。


5
你是为了给我们带来这个有价值的贡献而创建账户的吗? - anon
在C语言中,在可以设置EOF标志的操作之前调用feof绝对是一个逻辑错误。而fopen不属于这些操作之一。 - Evan Teran
Arrrggghhh! 这绝对不是错误,无论是逻辑上的、语法上的还是其他方面的。它是完全有效的。如果你理解它的作用 - 它会像MightyE上面解释的那样按预期行事。问题将条件框定为错误;这不是错误。 - Anonymous

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接