feof判断到结尾了 fgets还是获取一行空的 导致多读取一行

PHP 5.4.35 Released

fflush »

« fclose

Change language:              
English
             
Brazilian Portuguese
             
Chinese (Simplified)
             
French
             
German
             
Italian
             
Japanese
             
Romanian
             
Russian
             
Spanish
             
Turkish
             
Other

Edit Report a Bug

feof

(PHP 4, PHP 5)

feof — 测试文件指针是否到了文件结束的位置

说明

bool feof ( resource $handle )

测试文件指针是否到了文件结束的位。

参数

handle

文件指针必须是有效的,必须指向由 fopen() 或 fsockopen() 成功打开的文件(并还未由 fclose() 关闭)。

返回值

如果文件指针到了 EOF 或者出错时则返回 TRUE,否则返回一个错误(包括 socket 超时),其它情况则返回 FALSE

注释

Warning

如果服务器没有关闭由 fsockopen() 所打开的连接,feof() 会一直等待直到超时。要解决这个问题可参见以下范例:

Example #1 处理 feof() 的超时

<?php
function safe_feof($fp, &$start = NULL) {
 $start = microtime(true);

return feof($fp);
}

/* $fp 的赋值是由之前 fsockopen() 打开  */

$start = NULL;
$timeout = ini_get(‘default_socket_timeout‘);

while(!safe_feof($fp, $start) && (microtime(true) - $start) < $timeout)
{
 /* Handle */
}
?>

Warning

如果传递的文件指针无效可能会陷入无限循环中,因为 feof() 不会返回 TRUE

Example #2 使用无效文件指针的 feof() 例子

<?php
// 如果文件不可读取或者不存在,fopen 函数返回 FALSE
$file = @fopen("no_such_file", "r");

// 来自 fopen 的 FALSE 会发出一条警告信息并在这里陷入无限循环
while (!feof($file)) {
}

fclose($file);
?>

 add a note

User Contributed Notes 14 notes

up

down

4

sudo dot adam dot carruthers at gmail dot com

4 years ago

When using feof() on a TCP stream, i found the following to work (after many hours of frustration and anger):

NOTE: I used ";" to denote the end of data transmission.  This can be modified to whatever the server‘s end of file or in this case, end of output character is.

<?php
        $cursor = "";
        $inData = "";

while(strcmp($cursor, ";") != 0) {
            $cursor = fgetc($sock);
            $inData.= $cursor;
        }
        fclose($sock);
        echo($inData);
?>

Since strcmp() returns 0 when the two strings are equal, it will return non zero as long as the cursor is not ";".  Using the above method will add ";" to the string, but the fix for this is simple.

<?php
        $cursor = "";
        $inData = "";

$cursor = fgetc($sock);
        while(strcmp($cursor, ";") != 0) {
            $inData.= $cursor;
        }
        fclose($sock);
        echo($inData);
?>

I hope this helps someone.

up

down

5

ironoxid at libero dot it

8 years ago

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 ;)

up

down

4

Tom

8 years ago

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...

up

down

2

Alwar

1 year ago

Don‘t use feof to test if you have readed all data sent by the other end of the socket. As i know it would return true only when the other end closes the connection.

up

down

1

Jet

7 years ago

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);

up

down

1

cmr at forestfactory dot de

7 years ago

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);
?>

up

down

1

dewi at dewimorgan dot com

2 years ago

Return values in the documentation are incorrectly stated. It says:

Returns TRUE if the file pointer is at EOF or an error occurs (including socket timeout); otherwise returns FALSE.

Correct text would be more like:

Returns FALSE if no filehandle was passed; 
returns NULL if no filehandle was passed; 
returns TRUE if the file pointer is at EOF or an error occurs (including socket timeout);
otherwise returns FALSE.

As an example, running the following from the commandline:

php -r ‘echo 
    "Empty: ".var_export(feof(), true)."\n".
    "Null: ".var_export(feof(NULL), true)."\n".
    "Undefined: ".var_export(feof($undef), true)."\n"
;‘

This will output:

PHP Warning:  Wrong parameter count for feof() in Command line code on line 1
PHP Warning:  feof(): supplied argument is not a valid stream resource in Command line code on line 1
PHP Warning:  feof(): supplied argument is not a valid stream resource in Command line code on line 1

Empty: NULL
Null: false
Undefined: false

This can, as other commenters have reported, result in infinite loops and massive PHP error logfiles, if the file handle returned by fopen() is invalid for any reason.

up

down

1

honzam+php at ipdgroup dot com

6 years ago

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.

up

down

0

jakicoll

4 years ago

Please note that feof() used with TCP-Connections, returns false as long as the connection is open.
It even returns false when there is no data available.

BTW: Using feof() with HTTP for a single request, you should always make sure that you set the HTTP-Header "Connection" to "close" and _not_ to "keep-alive".

up

down

0

Anonymous

9 years ago

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.

up

down

0

Johannes

10 years ago

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‘.

up

down

-1

Anonymous

8 years ago

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.

up

down

-2

m a p o p a at g m a i l. c o m

8 years ago

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);
    }

up

down

-1

Anonymous

9 years ago

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.

 add a note

时间: 2024-11-05 22:05:26

feof判断到结尾了 fgets还是获取一行空的 导致多读取一行的相关文章

c# 判断字符是否是全角, 获取字符串的字节数 , 获取字符串指定长度字节数的字符串

1 Encoding.Default.GetByteCount(checkString);  =2 全角 =1 半角 /// <summary> /// 获取字符串的字节长度 /// </summary> /// <param name="str"></param> /// <returns></returns> public static int GetStringByteLength(this string s

【trim()】去掉字符串开头和结尾的空格,防止不必要的空格导致的错误。

去掉字符串开头和结尾的空格,防止不必要的空格导致的错误. public static void main(String arg[]){ String a=" abc"; String b="abc"; System.out.println(b.equals(a)); a=a.trim();//去掉字符串中的空格 System.out.println(a.equals(b)); }

字符串的截取,判断字符串是否相等和字符串是否为空的方法总结Java,Android

最近做项目Android时遇到了字符串的截取,判断字符串是否相等和字符串是否为空问题刚好用的上自己也知道些,所以整理了方便以后用,和供大家参考,有什么更好的方法或者其它方法我么可以一起交流,谢谢大家! 一.可以用subSequence方法截取任意长度的字符 例如: String s="AndroidandJava"System.out.println(s.subSequence(0, 1)); 运行结果为:A 原方法为:String.subSequence(beginIndex(开始字

使用feof()判断文件结束时会多输出内容的原因

这是原来的代码: #include <stdio.h>int main(){    FILE * fp;    int ch;    fp = fopen("d:\\aaaaa\\1.txt","r");    while (!feof(fp))    {        ch = getc(fp);        putchar(ch);    }    fclose(fp);    return 0;} 以此来输出时会发现好像输出的内容在结尾部分多了一

java判断开头结尾

1 String str="asdfghjklzxcvbnmqwertyuiop"; 2 if(str.indexOf("asd")==0); 3 { 4 System.out.println("判断字符串的开头为:"+str.indexOf("asd")); 5 } 6 System.out.println("判断字符串的结尾为:"+str.indexOf("p"));

js判断图片加载完成后获取图片实际宽高

通常,我们会用jq的.width()/.height()方法获取图片的宽度/高度或者用js的.offsetwidth/.offsetheight方法来获取图片的宽度/高度,但这些方法在我们通过样式设置了图片的宽高后获取的就不是图片的实际宽高,这显然在有些时候不是我们想要的结果,那么有没有一种方法来获取这样的实际宽高呢?答案是有的.下面的代码就能解决这样的问题: <img src="01.jpg" id="test" width="250px"

微信小程序判断用户是否需要再次授权获取个人信息

一.index.js设置如下 //获取用户的授权信息,放到本地缓存中 wx.getSetting({ success: (res) => { if(res.authSetting['scope.userInfo']) { wx.setStorage({ key: 'can_getuserinfo', data: 1, }) } else { wx.setStorage({ key: 'can_getuserinfo', data: 0, }) } } }), //1:从本地缓存中获取数据,如果获

jQuery获取动态表格中checkbox被选中一行的属性数据

http://www.jianshu.com/p/0ec66caf4c40 jQuery获取表格中checkbox被选中一行的属性数据

javascript判断对象、字符串、数组是否为空(兼容绝大部分浏览器)

// 用变量保存可以加速对对象原型的hasOwnProperty的访问. var hasOwnProperty = Object.prototype.hasOwnProperty; function isEmpty(obj) { // 本身为空直接返回true if (obj == null) return true; // 然后可以根据长度判断,在低版本的ie浏览器中无法这样判断. if (obj.length > 0) return false; if (obj.length === 0)