ifstream 不会加载整个文件

ifstream doesn't load whole file

本文关键字:文件 加载 ifstream      更新时间:2023-10-16

这个主题的名称可能不正确,但我不知道如何命名这个问题。 关于背景,我正在编写一个游戏,其中 3d 表面分为块。我想出了一种保存机制,其中所有块对象及其属性都以压缩形式保存到无序映射中,然后将其序列化为文件,因此可以根据当前需求有效地加载和保存世界的某些部分。 当然,在加载时,文件被加载,反序列化为无序映射,字符串被实时转换为块对象。 这是一个计划,但在实现方面存在难题。

我尝试了所有可能的搜索,但没有结果。 在我玩测试的过程中,我写了一个小的测试脚本,如下所示:

#include <iostream>
#include <fstream>
#include <sstream>
int main()
{
std::ifstream reader("output.dat", std::ios::binary);
std::string data;
reader>>data;
reader.close();
std::cout<<data.size()<<std::endl;
std::stringstream ss;
ss.str(data);
unsigned char id_prefix=0, zone_prefix=1;
while (ss.peek()!=EOF)
{
unsigned char type;
ss>>type;
if (type==id_prefix)
{
unsigned char tempx, tempy, tempz;
unsigned short tempid;
if (!(ss>>tempx)) std::cout<<"reading of x failed."<<std::endl;
if (!(ss>>tempy)) std::cout<<"Reading of y failed"<<std::endl;
if (!(ss>>tempz)) std::cout<<"Reading of z failed."<<std::endl;
if (!(ss>>tempid)) std::cout<<"Reading of id failed, position is "+std::to_string(ss.tellg())+", values are "+std::to_string(type)+" "+std::to_string(tempx)+" "+std::to_string(tempy)+" "+std::to_string(tempz)<<std::endl;
std::cout<<(int)tempx<<" "<<(int)tempy<<" "<<(int)tempz<<" "<<(int)tempid<<std::endl;
}
else if (type==zone_prefix)
{
unsigned char tempx, tempy, tempz;
unsigned int tempzone;
ss>>tempx;
ss>>tempy;
ss>>tempz;
ss>>tempzone;
std::cout<<(int)tempx<<" "<<(int)tempy<<" "<<(int)tempz<<" "<<(int)tempzone<<std::endl;
}
}
}

输出.dat是一个带有一个实验性解压缩块的文件,用于重现游戏中的解析过程。 您可以从以下位置下载: https://www.dropbox.com/s/mljsb0t6gvfedc5/output.dat?dl=1 如果需要,它的大小约为 160 KB。这是第一个问题。 这可能只是我的愚蠢,但我认为当我使用 std::ios::binary 打开 ifstream,然后将其内容提取为字符串时,它会加载整个文件,但它只加载前 46 个字节。 这是第一个问题,接下来在游戏中,我使用其他系统加载有效的数据,但是在代码的下半部分可以看到的字符串流处理在这个位置附近也失败了。 我想数据也存在问题,如您所见,格式是 uchar 类型(指示以下字节是指 id 还是区域)、坐标(每个为 uchar),如果是 id,则为 ushort,如果是区域,则为 uint。 但是当我使用自己创建的二进制编辑器查看文件时,它仅将 id 显示为一个字节,而不是我从短值中预期的两个字节。保存也是使用字符串流完成的,形式如下: 无符号短时间 = 3;示例值 SS<<p>在结果文件中,这表示为 51(在一个字节中),3 的 ASCII 代码是什么,所以我有点困惑,或者只不过是一点点。

你能帮我这个吗?我在win7 64位上使用Mingw g ++ 4.9.3。

多谢!

从1.1.2017编辑

现在整个文件在字符串流中读取,但提取值仍然失败。 当提取>>读取下一个空格时,例如提取到无符号短篇的情况如何? 我正在玩代码位,试图将例如无符号的短 tempid 更改为无符号的 char tempid。 输出对我来说没有意义。 在简短版本中,字节如下: 0;1;0;0;51 被解读为类型 0、x 1、y 0、z 0 和 id 3 是正确的,即使我不明白为什么在这里是 51 而不是 3。 之前写到流似乎是:

unsigned short idtowrite=3;
ss<<idtowrite;

但是当我将无符号的短 tempid 更改为无符号的 char tempid 时,它将其读取为类型 0、x 1、y 0、z 0 和 id 51,这是不正确的,但我希望它来自写入文件。 如果它通过完整流正确读取,我不会解决它,但出于某种原因直到 0;8;0;0;51 一切都是正确的,从 0 开始;9;0;0;旁边的 51 失败,x 读取为 0,y 读取为 0,z 为 51,并且设置 EOF。 我在想阅读是否没有错过一个字节,但我看不出这样做的理由。 你能推荐我一些有效且有效的方法如何在字符串流中存储值吗?

提前感谢!

std::ios::binary仅具有抑制行尾转换的效果(例如 文件中rn不会转换为仅n内存中)。在处理二进制文件时提供这个当然是正确的。

但是,>>仍然是格式化的输入函数,它跳过前导空格,在空格处终止,依此类推。

如果要实际将文件作为二进制数据读取,则必须对流对象使用read函数。