Вопрос

Я имею опыт работы с 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_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 немного рискован, но это нормально).Конечно, это сработает не во всех ситуациях...

Есть ли что-то, чего мне не хватает в исходном вопросе, что делает этот подход невозможным?

Ваше утверждение о том, что я не звоню feof перед fread неверно - следовательно вопрос некорректен.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top