C++ ifstream不能完全读取整个数据

C++ ifstream不能完全读取整个数据,c++,byte,ifstream,C++,Byte,Ifstream,我正试图逐块读取文件。块大小为64字节。但是还剩下一些字节 示例:我有一个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++;

我正试图逐块读取文件。块大小为64字节。但是还剩下一些字节

示例:我有一个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;
typedef无符号字符uint1;
ifstream是(path.c_str(),ifstream::in | ifstream::binary);
uint1数据[64];
int i=0;
而(is.read((char*)数据,64)){
i++;
}

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

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


所以,最后一个是.read的返回值被计算为“false”,并且它不被您的计数器计数

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

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


所以,最后一个是.read的返回值被计算为“false”,并且它不被您的计数器计数

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

您可能希望在上次读取后检查的值:

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

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

您可能希望在上次读取后检查的值:

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

如果您的目标实际上是读取文件,而不是像示例那样简单地计算块数,那么您可能希望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 + "'" ); 
} 
std::ifstream是(path.c_str(),std::ios_base::binary);//始终为ifstream设置in模式
如果(!is)
抛出std::runtime_错误(“无法打开文件“”+path+”);
而(!is.eof())
{
std::arraybuf;
is.peek();//由于缓冲的原因,需要使用此选项。
const auto n=is.readsome(buf.data(),buf.size());
如果(是)
handle_block(buf,n);//std::cout.write(buf.data(),n)
其他的
抛出std::runtime_错误(“读取文件时出错”“+path+””);
} 

如果您的目标实际上是读取文件,而不是像示例那样简单地计算块的数量,那么您可能需要这样的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 + "'" ); 
} 
std::ifstream是(path.c_str(),std::ios_base::binary);//始终为ifstream设置in模式
如果(!is)
抛出std::runtime_错误(“无法打开文件“”+path+”);
而(!is.eof())
{
std::arraybuf;
is.peek();//由于缓冲的原因,需要使用此选项。
const auto n=is.readsome(buf.data(),buf.size());
如果(是)
handle_block(buf,n);//std::cout.write(buf.data(),n)
其他的
抛出std::runtime_错误(“读取文件时出错”“+path+””);
} 

结尾处“i”的值是多少?对于ValeryShevchuk和Angewwhat是结尾处“i”的值?对于ValeryShevchuk和AngewYes,“i”的值是5,对于ValeryShevchuk和AngewYes,我知道。没有简单的方法将文件的数据加载到块中吗?@tbol,您的最后一个块已正确加载,但您必须使用“istream::gcount”检查从流中读取了多少字节,这样您就可以安全地在“data”数组中使用第一个istream::gcount()字节了。很多字节都是明确存储的。是的,我知道。没有简单的方法将文件的数据加载到块中吗?@tbol,您的最后一个块加载正确,但您必须使用“istream::gcount”检查从流中读取了多少字节,这样您就可以安全地大量使用“data”数组中的第一个istream::gcount()字节,字节被最终存储。我的目标是从文件中读取字节,并且无论读取是否成功,我都使用计数器获得响应。我只是忘了检查最后一个字节块是否真的被读取了。thx非常感谢您的帮助,但是我现在已经有了一个读取字节的解决方案。我的目标是从文件中读取字节,并且我已经使用计数器来获得响应,无论读取是否成功。我只是忘了检查最后一个字节块是否真的被读取了。谢谢你的帮助,但我现在已经有了一个读取字节的解决方案。