【发布时间】:2017-12-30 21:37:26
【问题描述】:
这个主题的名称可能不正确,但我不知道如何命名这个问题。 关于背景的东西,我正在编写一个游戏,它的 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;
}
}
}
Output.dat 是一个包含一个实验性解压缩块的文件,用于重现游戏中的解析过程。 您可以从以下位置下载它: https://www.dropbox.com/s/mljsb0t6gvfedc5/output.dat?dl=1 如果需要,它的大小约为 160 kb。这是第一个问题。 这可能只是我的愚蠢,但我认为当我使用 std::ios::binary 打开 ifstream,然后将其内容提取到字符串时,它会加载整个文件,但它只加载了前 46 个字节。 这是第一个问题,接下来在游戏中,我使用其他系统加载了有效的数据,但是从代码的下部可以看出,在这个位置附近的字符串流处理也失败了。 我猜数据也有问题,如您所见,格式是 uchar 类型(指示后面的字节是指 id 还是 zone)、坐标(每个都为 uchar),如果是 id,则为 ushort,如果是 zone 则为 uint。 但是当我用自己创建的二进制编辑器查看文件时,它只显示 id 一个字节,而不是我对短值所期望的两个。保存也是用 stringstream 完成的,形式为: 无符号短 tempid=3; //示例值 ss
在结果文件中,这表示为 51(一个字节),什么是 3 的 ascii 代码,所以我有点困惑,或者说是一点点。
你能帮我解决这个问题吗?我在 win7 64 位上使用 Mingw g++ 4.9.3。
非常感谢!
从 1.1.2017 开始编辑
现在整个文件都在 stringstream 中读取,但值的提取仍然失败。 当 >> 提取读取到下一个空格时,例如提取到无符号短的情况如何? 我正在玩代码位,试图将例如 unsigned short tempid 更改为 unsigned char tempid。 输出对我来说没有意义。 简而言之,字节如下: 0;1;0;0;51 被读取为类型 0、x 1、y 0、z 0 和 id 3 什么是正确的,即使我不明白为什么这里是 51 而不是 3。 之前写入流似乎是:
unsigned short idtowrite=3;
ss<<idtowrite;
但是当我将 unsigned short tempid 更改为 unsigned 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。 我在想如果阅读没有错过一个字节,但我没有理由这样做。 你能推荐我一些有效且可行的方法来将值存储在字符串流中吗?
提前致谢!
【问题讨论】:
-
reader>>data最多读取第一次出现的空白字符。试试这个:std::stringstream ss; ss << reader.rdbuf();- 这应该将文件的全部内容吞入字符串流中。 -
什么是“reader.close();”创建 sreader fstream 后立即?
-
你所有的阅读都假设内容是文本,但事实并非如此。
-
哦,谢谢! Rdbuf 变体完美运行。但是现在我对代码的第二部分有问题,从 stringstream 读取。我在为这篇文章添加扩展名时遇到了问题,只有在创建新问题后我才知道原因。对不起,这是我关于stackoverflow的第一个问题。您可以在stackoverflow.com/questions/48053097/… 找到新问题,感谢您的理解。
标签: c++