Johannes: Remember note from stream_get_meta_data page: For socket streams this member [eof] can be TRUE even when unread_bytes is non-zero. To determine if there is more data to be read, use feof() instead of reading this item.
Another thing: better not rely on the "including socket timeout" part of when feof returns true. Just found program looping two days in while(!feof($fd)) fread ... with 20 seconds timeout in PHP 4.3.10.
feof
(PHP 4, PHP 5)
feof — ファイルポインタがファイル終端に達しているかどうか調べる
説明
bool feof
( resource $handle
)
ファイルポインタがファイル終端に達しているかどうかを調べます。
パラメータ
- handle
-
ファイルポインタは、有効なファイルポインタである必要があり、 fopen() または fsockopen() で正常にオープンされた (そしてまだ fclose() でクローズされていない) ファイルを指している必要があります。
返り値
ファイルポインタが EOF に達しているかまたはエラー (ソケットタイムアウトを含みます) の場合に TRUE 、 その他の場合に FALSE を返します。
注意
警告
もし fsockopen() でオープンされた接続がサーバによって 閉じられていない場合、feof() はタイムアウトになるまで待ち、TRUE を返します。 デフォルトのタイムアウト値は 60 秒です。この値を変更するには stream_set_timeout() を使用します。
警告
無効なファイルポインタを渡した場合、無限ループに陥ることがあります。 なぜなら EOF が TRUE を返すことができないからです。
例1 feof() に無効なファイルポインタを使用する例
<?php
// ファイルを読み込めなかったりファイルが存在しなかったりした場合、
// fopen 関数は FALSE を返します。
$file = @fopen("no_such_file", "r");
// fopen からの FALSE が警告を発生させ、ここで無限ループとなります。
while (!feof($file)) {
}
fclose($file);
?>
feof
honzam+php at ipdgroup dot com
28-Feb-2008 07:17
28-Feb-2008 07:17
Jet
19-Sep-2007 11:03
19-Sep-2007 11:03
To avoid infinite loop with fgets() just use do..while statement.
<?php
if ($f = fopen('myfile.txt', 'r')) do {
$line = fgets($f);
// do any stuff here...
} while (!feof($f));
fclose($f);
cmr at forestfactory dot de
20-Nov-2006 01:57
20-Nov-2006 01:57
Here's solution 3:
<?
$fp = fopen("myfile.txt", "r");
while ( ($current_line = fgets($fp)) !== false ) {
// do stuff to the current line here
}
fclose($fp);
?>
AFAICS fgets() never returns an empty string, so we can also write:
<?
$fp = fopen("myfile.txt", "r");
while ( $current_line = fgets($fp) ) {
// do stuff to the current line here
}
fclose($fp);
?>
Tom
25-Oct-2006 07:27
25-Oct-2006 07:27
feof() is, in fact, reliable. However, you have to use it carefully in conjunction with fgets(). A common (but incorrect) approach is to try something like this:
<?
$fp = fopen("myfile.txt", "r");
while (!feof($fp)) {
$current_line = fgets($fp);
// do stuff to the current line here
}
fclose($fp);
?>
The problem when processing plain text files is that feof() will not return true after getting the last line of input. You need to try to get input _and fail_ before feof() returns true. You can think of the loop above working like this:
* (merrily looping, getting lines and processing them)
* fgets used to get 2nd to last line
* line is processed
* loop back up -- feof returns false, so do the steps inside the loop
* fgets used to get last line
* line is processed
* loop back up -- since the last call to fgets worked (you got the last line), feof still returns false, so you do the steps inside the loop again
* fgets used to try to get another line (but there's nothing there!)
* your code doesn't realize this, and tries to process this non-existent line (typically by doing the same actions again)
* now when your code loops back up, feof returns true, and your loop ends
There's two ways to solve this:
1. You can put an additional test for feof() inside the loop
2. You can move around your calls to fgets() so that the testing of feof() happens in a better location
Here's solution 1:
<?
$fp = fopen("myfile.txt", "r");
while(!feof($fp)) {
$current_line = fgets($fp);
if (!feof($fp)) {
// process current line
}
}
fclose($fp);
?>
And here's solution 2 (IMHO, more elegant):
<?
$fp = fopen("myfile.txt", "r");
$current_line = fgets($fp);
while (!feof($fp)) {
// process current line
$current_line = fgets($fp);
}
fclose($fp);
?>
FYI, the eof() function in C++ works the exact same way, so this isn't just some weird PHP thing...
ironoxid at libero dot it
06-Jun-2006 10:52
06-Jun-2006 10:52
I really thought that the feof() was TRUE when the logical file pointer is a EOF.
but no !
we need to read and get an empty record before the eof() reports TRUE.
So
$fp = fopen('test.bin','rb');
while(!feof($fp)) {
$c = fgetc($fp);
// ... do something with $c
echo ftell($fp), ",";
}
echo 'EOF!';
prints for two time the last byte position.
If our file length is 5 byte this code prints
0,1,2,3,4,5,5,EOF!
Because of this, you have to do another check to verify if fgetc really reads another byte (to prevent error on "do something with $c" ^_^).
To prevent errors you have to use this code
$fp = fopen('test.bin','rb');
while(!feof($fp)) {
$c = fgetc($fp);
if($c === false) break;
// ... do something with $c
}
but this is the same of
$fp = fopen('test.bin','rb');
while(($c = fgetc($fp))!==false) {
// ... do something with $c
}
Consequently feof() is simply useless.
Before write this note I want to submit this as a php bug but one php developer said that this does not imply a bug in PHP itself (http://bugs.php.net/bug.php?id=35136&edit=2).
If this is not a bug I think that this need at least to be noticed.
Sorry for my bad english.
Bye ;)
m a p o p a at g m a i l. c o m
03-Jun-2006 09:58
03-Jun-2006 09:58
you can avoid the infinite loop and filling the error logs
by an simple if statement
Here is the example
$handle = fopen("http://xml.weather.yahoo.com/forecastrss?p=AYXX0008&u=f", "r");
$xml = "";
if ($handle)
{
while (!feof($handle))
{
$xml .= fread($handle, 128);
}
fclose($handle);
}
02-Jan-2006 11:27
if you use fseek function to pos the pointer exceed the size the file,feof still return true.so note that when you use feof as the condition of while loop.
01-Aug-2005 02:21
if you hit an feof() infinite loop, watch out for resultant humongous logs, they can cripple a site with hard disk usage limits or run up excess usage fees.
05-Mar-2005 02:02
if you're worried the file pointer is invalid, TEST IT before you go into your loop... that way it'll never be an infinite loop.
Johannes
12-Mar-2004 07:47
12-Mar-2004 07:47
I found feof() to be a slow function when using a non-blocking connection.
The function stream_get_meta_data() returns much quicker and has a return field 'eof'.