PHP的feof行为与C的关系

时间:2010-07-13 16:57:31

标签: php feof

我来自C和C ++背景,但也玩一些网络内容。我们所有的C人(希望)知道在进行读取之前在feof上调用FILE*是一个错误。这是经常咒骂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 feof之前调用fread是不正确的?

有几种方法可以让PHP以不同的方式完成C的版本,但我觉得它们有缺点。

  • 他们可以默认为!EOF。这是次优的,因为对于某些角落情况可能不正确。

  • 他们可以在fopen调用期间获取文件大小,但这不适用于所有类型的文件资源,导致行为不一致且速度会慢。

3 个答案:

答案 0 :(得分: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)不会返回任何数据,并且您正在执行的任何处理都不会处理任何数据。如果你真的需要知道你是否在文件的末尾,你必须先阅读。

答案 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有点冒险,但没关系)。当然,这不适用于所有情况......

原始问题中是否存在一些让这种方法不可行的东西?

答案 2 :(得分:-1)

关于在feof之前未调用fread的说法不正确 - 因此问题无效。