题
我有 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);
但这不是重点。我尝试测试如果我以“错误的方式”做事是否会失败,但我无法让它导致不正确的行为。这并不完全科学,但我认为值得一试。
那么,这样的调用方式是不是不正确呢? feof
之前 fread
在 PHP 中?
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);
?>
您将得到一行读数 read 0 bytes
. 。feof() 返回 true,即使您在技术上位于文件末尾。通常这不会造成问题,因为 fread($fp, 1)
不返回任何数据,并且您对其进行的任何处理都不能很好地处理任何数据。如果您确实需要知道是否位于文件末尾,则必须先进行读取。
其他提示
这可能更像是一个问题而不是答案,但为什么不使用 文件获取内容()?根据我的经验,如果您正在读取文件或流,此函数会为您完成脏工作(假设您想要将整个资源读取到字符串,或者知道/可以计算限制和偏移量)。它的姊妹函数 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 有点冒险,但没关系)。当然,这并不是在所有情况下都有效......
我在最初的问题中是否遗漏了一些东西,导致这种方法不可行?
你关于不打电话的断言 feof
之前 fread
不正确 - 因此该问题无效。