ifstream没有加载整个文件

时间:2017-12-30 21:37:27

标签: c++

此主题的名称可能不正确,但我不知道如何命名此问题。 关于背景的东西,我正在编写一个游戏,其中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,区域为uint。 但是当我用自己创建的二进制编辑器查看文件时,它只显示了一个字节的id,而不是我从短期值中预期的两个字节。使用stringstream进行保存,形式如下: unsigned short tempid = 3; //示例值 SS&LT;

在结果文件中,这表示为51(在一个字节中),什么是3的ascii代码,所以我很困惑,或者只是一点点。

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

非常感谢!

从1.1.2017编辑

现在整个文件在stringstream中读取,但值的提取仍然失败。 当&gt;&gt;提取读取到下一个空格,例如,如何提取到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,这是不正确的,但我希望它来自writed文件。 如果它通过全流正确读取,我将无法解决它,但由于某种原因,直到0; 8; 0; 0; 51都是正确的,并且从0; 9; 0; 0; 51,它是旁边的失败,x为0,y为0,z为51,EOF设置。 我在想,如果读书没有错过一个字节,但我没有理由这样做。 能否请您推荐一些有效且有效的方法如何在stringstream中存储值?

提前致谢!

1 个答案:

答案 0 :(得分:2)

x <- "fileName1.doc Author=Name fileName2.doc Author=Name fileName2.doc Author=Name" 仅具有抑制行尾转换的效果(例如,文件中的std::ios::binary不会仅转换为内存中的\r\n。处理二进制文件时提供这一点当然是正确的。

但是,\n仍然是格式化的输入函数,它跳过前导空格,终止于空格等等。

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