PHP 的 feof 行为与 C 的行为

PHP's feof behavior versus C's

提问人:Evan Teran 提问时间:7/14/2010 最后编辑:CommunityEvan Teran 更新时间:7/14/2010 访问量:565

问:

我有 C 和 C++ 背景,但也玩一些网络东西。我们所有 C 人员(希望)都知道在进行读取之前调用 a 是错误的。这是经常刺痛 C 和 C++ 新手的东西。PHP的实现也是这样吗?feofFILE*

我认为这一定是因为文件可能是一个套接字或其他任何在完成读取之前无法知道大小的东西。但是几乎每个PHP示例(甚至是我见过的 php.net 上找到的PHP示例看起来都是这样的(并且警报在我的脑海中响起):

$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

PHP 的 feof

评论


答:

3赞 MightyE 7/14/2010 #1

PHP 不知道它是否在文件的末尾,直到您尝试从中读取它。试试这个简单的例子:

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

您将获得一行阅读。feof() 返回 true,即使您在技术上位于文件末尾。通常这不会导致问题,因为不返回任何数据,并且您正在执行的任何处理都不会处理任何数据。如果你真的需要知道你是否在文件的末尾,你必须先进行读取。read 0 bytesfread($fp, 1)

-1赞 Anonymous 7/14/2010 #2

您关于不在 an 之前打电话的断言是不正确的 - 因此这个问题是无效的。feoffread

评论

5赞 7/14/2010
您创建帐户只是为了给我们这个宝贵的贡献吗?
0赞 Evan Teran 7/14/2010
在 C 中,在可以设置 EOF 标志的操作之前调用肯定是一个逻辑错误。 不是这些操作之一。feoffopen
0赞 Anonymous 7/20/2010
啊它肯定不是一个错误,无论是逻辑上的、句法上的还是其他方面的。这是完全有效的。如果您了解它的作用 - 它的行为将完全符合预期,正如上面的 MightyE 所解释的那样。该问题将条件描述为错误;事实并非如此。
0赞 TCCV 7/14/2010 #3

这可能更像是一个问题而不是答案,但为什么不使用 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:[email protected]/file.txt", $real_content, 0, $stream);
}

然后你不需要担心EOF或任何东西,它会为你做(ftp put有点危险,但没关系)。当然,这并非在所有情况下都有效......

我在原来的问题中是否遗漏了一些东西,使这种方法不可行?

评论

1赞 Evan Teran 7/14/2010
你的方法很好,完全合理,我的问题更多的是学术性的,而不是实用的。我只是想知道PHP中的行为是否与C中的行为相同。foef
1赞 TCCV 7/14/2010
啊,一个学者,我没看到你的皮夹克有粗花呢肘部 8o)(荷马辛普森 FTW,“更正,我毁了两件夹克!