+ -
当前位置:首页 → 问答吧 → 问个fread的未知问题

问个fread的未知问题

时间:2010-07-02

来源:互联网

本帖最后由 houtinghua 于 2010-07-02 11:21 编辑

fread一个打开的文件流,文件长度100;
int r = fread( buf,1,100,fp );
这个时候fread有没有可能返回70,我的意思是说fread的过程中没有发生普通意义上的错误,只是一次没读那么多,让你再fread一次,读取100-70=30个字节呢?

因为我看函数介绍说fread返回实际读取的,但是没有确切说明实际读取的字节必须等于100

不知道你们看明白我想说什么了吗


把下面的提上来  怕你们不往下看



QUOTE:
以返回的长度为准。如果不足是要再读的。至于这种情况是否发生,和平台以及fread()实现情况有关。你不能假设 ...
没本 发表于 2010-07-02 10:59




    我就等你最后一句话呢  那么找你的意思,读文件应该着这么找写了?
  1. int len = 100;//文件实际长度,已知
  2. int r = 0;
  3. while ( len>0 )
  4. {
  5.     r = fread(buf,1,len,fp);
  6.     len-=r;
  7. }
  8. ...
复制代码

作者: houtinghua   发布时间: 2010-07-02

有错或者到达文件尾才会返回小于要求读的数

作者: hellioncu   发布时间: 2010-07-02

size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream);
fread()会返回实际读取到的nmemb数目,如果此值比参数nmemb 来得小,则代表可能读到了文件尾或有错误发生,这时必须用feof()或ferror()来决定发生什么情况。

作者: ^^   发布时间: 2010-07-02



QUOTE:
有错或者到达文件尾才会返回小于要求读的数
hellioncu 发表于 2010-07-02 10:54




    也就是说文件实际长度100,我fread  100,那么返回结果肯定是100?

作者: houtinghua   发布时间: 2010-07-02



QUOTE:
也就是说文件实际长度100,我fread  100,那么返回结果肯定是100?
houtinghua 发表于 2010-07-02 10:56




    没错的情况下

作者: hellioncu   发布时间: 2010-07-02

以返回的长度为准。如果不足是要再读的。至于这种情况是否发生,和平台以及fread()实现情况有关。你不能假设r只能是失败或者100。

作者: 没本   发布时间: 2010-07-02

冗余检查是必需的

作者: rain_fish   发布时间: 2010-07-02



QUOTE:
以返回的长度为准。如果不足是要再读的。至于这种情况是否发生,和平台以及fread()实现情况有关。你不能假设 ...
没本 发表于 2010-07-02 10:59




    我就等你最后一句话呢  那么找你的意思,读文件应该着这么找写了?
  1. int len = 100;//文件实际长度,已知
  2. int r = 0;
  3. while ( len>0 )
  4. {
  5.     r = fread(buf,1,len,fp);
  6.     len-=r;
  7. }
  8. ...
复制代码

作者: houtinghua   发布时间: 2010-07-02

是的,还有判断r返回0的情况,要不就死循环了。

作者: 没本   发布时间: 2010-07-02

o~~~~~~~~~~~~~~~~~~~~~~~原来如此

作者: houtinghua   发布时间: 2010-07-02

本帖最后由 marxn 于 2010-07-02 15:24 编辑

如果是磁盘文件就不需要判断。fread在读取磁盘文件时,只有读完了指定的字节数或者:
1、到了文件末尾
2、发生错误
的时候才会出现实际读取的字节数小于指定字节数的现象。

如果是由fdopen打开socket产生的stream,那么确实会出现实际读取的字节数小于指定字节数的现象。

作者: marxn   发布时间: 2010-07-02

本帖最后由 聪聪知不道 于 2010-07-02 19:18 编辑

这里用循环读取我觉得不太合适。

首先,我们要弄清我们在做什么:

如果我们要读一个文件并且读完为止,那么我们在读以前是没有必要知道这个文件究竟有多大的,那么这个100从何而来?

如果我们没有要求,就是要读100个字节,那如果本身这个文件就没有100个字节那么长怎么办?循环读取会造成死循环,这是不是我们想要的结果?(如果确定我们就要实现这种效果当然可以这么做,比如说网络编程)


如果我们已知一个文件有超过100个字节长,并且我们无脑的读100字节出来,那这时候实际上fread在读到数据以后只有两种返回值:a.返回-1,表示读取过程中发生异常;b.返回100。fread标准库是不会被信号打断的,标准库实现中已经为我们做好了被信号打断重读。

作者: 聪聪知不道   发布时间: 2010-07-02

我不知道LZ把我的回帖提前是什么意思,但LZ的循环体明显是有问题的。
  1. int len = 100;//文件实际长度,已知
  2. int r = 0;
  3. while ( len>0 )
  4. {
  5.     r = fread(buf,1,len,fp);
  6.     len-=r;
  7. }
复制代码
注意LZ没有判断返回值r==0的情况,这是程序员常见的问题,往往图方便不愿意写全容错代码。
我的改动意见如下:
  1.   total = 0;
  2.   while( !feof( stream )  && total<100 )
  3.    {
  4.       // Attempt to read in 100 bytes:
  5.       count = fread( buffer+total, sizeof( char ), 100, stream );
  6.       if( ferror( stream ) )      {
  7.          perror( "Read error" );
  8.          break;
  9.       }

  10.       // Total up actual bytes read
  11.       total += count;
  12.    }
复制代码

作者: 没本   发布时间: 2010-07-03

本帖最后由 没本 于 2010-07-03 02:11 编辑

如果文件长度100不是已知的话,还要调整fread中的读长度参数为100-total,以免缓冲区溢出。如不如此的话,为缓冲区多分配100字节也是一个好办法。因为文件长度有可能因某种原因改变,例如中病毒。程序员不能假设系统里一切都是按自己设想的存在,因此健壮的程序里必须处理各种意外。不要害怕烦琐而写出有缺陷的程序,给黑客制造攻击机会。

作者: 没本   发布时间: 2010-07-03