Я происхожу из C и фона C++, но также и играю с некоторым веб-материалом. Все нас люди C (надо надеяться), знают тот вызов feof
на a 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);
?>
Вы получите чтение одной строки , чтение 0 байтов
. feof () вернул истину, даже если технически вы были в конце файла. Обычно это не вызывает проблем, потому что 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
, неверно - следовательно, вопрос неверен.