ifstream 没有完全读取整个数据

ifstream does not completely read whole data

我正在尝试逐块读取文件。块大小为 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;

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

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

If the input sequence runs out of characters to extract (i.e., the end-of-file is reached) before n characters have been successfully read, the array pointed to by s contains all the characters read until that point, and both the eofbit and failbit flags are set for the stream.

因此,最后一个 is.read 的 return 值被评估为 "false" 并且您的计数器不计算它。

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

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

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

如果您的目标实际上是读取文件,而不是像示例那样简单地计算块数,那么您可能需要这样的东西:

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 + "'" ); 
}