ifstream没有完全读取整个数据

时间:2015-10-30 10:51:47

标签: c++ byte ifstream

我正在尝试逐块读取文件。 Blocksize是64Byte。但是剩下一些字节。

示例:我有一个360字节文件并以64字节块读取数据,因此我需要6次64字节块来获取所有数据。

typedef unsigned char uint1;

ifstream is(path.c_str(), ifstream::in | ifstream::binary);
uint1 data[64];
int i = 0;

while (is.read((char*)data, 64)) {        
    i++;
}

cout << i << endl;

但是我只得到完全填充的64字节块的5倍。如何获取剩余的字节?

3 个答案:

答案 0 :(得分:4)

我认为问题是你的文件大小不能被缓冲区大小整除,所以最后一个块的大小小于64(360 - 64 * 5 = 40字节)。对于这种情况,istream::read的文档说:

  

如果在成功读取n个字符之前输入序列用完了要提取的字符(即,到达文件结尾),则s指向的数组包含直到该点读取的所有字符,并且为流设置了eofbit和failbit标志。

因此,最后is.read的返回值被评估为“false”,并且您的计数器不计算它。

答案 1 :(得分:3)

360不能被64整除,这意味着最后一个块将不会被完整读取。咨询suitable documentation表明,阅读这样一个不完整的块会在您正在阅读的流上设置eofbitfailbit,这意味着您的while循环中的条件会进行评估到最后一个块的false。但是读取确实发生了并且数据存储正确。

您可能想要在上次阅读后检查gcount()的值:

while (is.read((char*)data, 64)) {        
    i++;
}
if (is.gcount() > 0) {
    i++;
}

答案 2 :(得分:0)

如果您的目标实际上是阅读文件,而不是简单地计算样本所做的块数,那么您可能想要这样的smth:

std::ifstream is( path.c_str(), std::ios_base::binary ); // in mode is always set for ifstream 

if( !is )
  throw std::runtime_error("unable to open file '" + path + "'" ); 

while( !is.eof() )
{
  std::array< char, 64 > buf;        
  is.peek(); // needs this because of the buffering.
  const auto n = is.readsome( buf.data(), buf.size() );
  if( is )
    handle_block( buf, n ); // std::cout.write( buf.data(), n )
  else
    throw std::runtime_error("error reading file '" + path + "'" ); 
}