由一个Bug看ifstream中read()与readsome()的区别

项目中读取特定二进制文件时,数据量超400K左右程序出错,最终发现是使用fsream::readsome()函数所致,改成fsream::read()即可。详细介绍了流的派生关系,指出read()和readsome()区别在于是否迫使同步缓冲区,还提及选择readsome()的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

ifstream中read()与readsome()的区别。

项目中出现一个很有趣的Bug,程序读入一个特定的二进制文件中的数据,进行一些处理,可是每当这个文件的数据量超过某个特定值(这个值不大,400K左右)的时候运行结果就出错。

追查Bug是程序员的一项基本功,也是最能体现实力的地方之一。这个Bug最终在3天追捕之后被一个同事抓获。原因确是因为我写的读取文件的模块中使用了fsream::readsome()函数。改成fsream::read()就可以了。

惊悸之余,特地比较详细的看了关于流的解释。

首先,fstream是basic_fstream模板类关于char的一个实例。

typedef basic_fstream<char, char_traits<char> > fstream;

basic_fstream的由basic_iostream派生的

template <class Elem, class Tr = char_traits<Elem> >
    class basic_fstream : public basic_iostream<Elem, Tr>

basic_iostream是由basic_istream和basic_ostream派生的。

template <class Elem, class Tr = char_traits<Elem> >
   class basic_iostream : public basic_istream<Elem, Tr>,
      public basic_ostream<Elem, Tr> 

我们使用的fstream::readsome实际上是 basic_istream::readsome().

而basic_istream是从basic_ios派生的

template <class Elem, class Tr = char_traits<Elem> >
   class basic_istream
      : virtual public basic_ios<Elem, Tr>

basic_ios是从ios_base派生的

template <class Elem, class Traits>
   class basic_ios : public ios_base
派生关系图如下:

 

在流的实现上,采取了缓冲区I/O的方式,每个stream对象中都有一个对于一个streambuf,对于流的操作缺省状态下是对于缓冲区的操作,直到出现迫使他和缓冲区同步的操作。

而read()和readsome()的区别就在于此,readsome()并不迫使同步缓冲区,而read()读取的时候,如果发现缓冲区中的数据不够,就试图从关联的数据源(这里就是文件)来读取。

readsome()函数之后调用gcount()可以检测究竟有多少字节被操作了。good()函数也可以检测,而我没有做。

 

我当初选择readsome()是以为read()是操作charactor的,而readsome()才是操作二进制的。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值