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()才是操作二进制的。