C ++二进制文件读取

时间:2012-10-11 14:46:42

标签: c++ binaryfiles file-io

我正在尝试将对象的对象保存在二进制文件中。

以下是文件代码的一些负载:

template <class T> void read(T* obj,std::ifstream * file) {
    file->read((char*)(obj),sizeof(*obj));
    file->seekg(int(file->tellg())+sizeof(*obj));
}

void read_db(DB* obj,std::ifstream * file) {
    read<DB>(obj,file);
    for(int index = 0;index < obj->Arrays.size();index++) {
        std::cin.get(); //debugging
        obj->Arrays[0].Name = "hi"; //debugging
        std::cin.get(); //debugging
        std::cout << obj->Arrays[0].Name;
        read<DB_ARRAY>(&obj->Arrays[index],file);
        for(int row_index = 0;row_index < obj->Arrays[index].Rows.size();row_index++) {
            read<DB_ROW>(&obj->Arrays[index].Rows[row_index],file);
            for(int int_index = 0;int_index < obj->Arrays[index].Rows[row_index].i_Values.size();int_index++) {
                read<DB_VALUE<int>>(&obj->Arrays[index].Rows[row_index].i_Values[int_index],file);
            }
        }
    }
}

这是DB / DB_ARRAY类

class DB {
public:
    std::string Name;
    std::vector<DB_ARRAY> Arrays;
    DB_ARRAY * operator[](std::string);
    DB_ARRAY * Create(std::string);
};
class DB_ARRAY {
public:
    DB* Parent;
    std::string Name;
    std::vector<DB_ROW> Rows;
    DB_ROW * operator[](int);
    DB_ROW * Create();
    DB_ARRAY(DB*,std::string);
    DB_ARRAY();
};

所以现在read_db函数的第一个参数将具有正确的值,并且对象上的向量Arrays具有正确的大小,但是如果我从obj-&gt; Arrays索引任何对象的任何值,它将抛出访问权限违规例外。

std::cout << obj->Arrays[0].Name; // error
std::cout << &obj->Arrays[0]; // no error

后者总是打印相同的地址,所以当我保存一个转换为char *的对象时,它是否也保存了它的地址?

2 个答案:

答案 0 :(得分:0)

正如各种评论者指出的那样,你不能简单地通过保存/恢复它的内存来序列化(非POD)对象。

实现序列化的常用方法是在类上实现序列化接口。像这样:

struct ISerializable {
   virtual std::ostream& save(std::ostream& os) const = 0;
   virtual std::istream& load(std::istream& is) = 0;
};

然后,在可序列化的类中实现此接口,在引用其他可序列化类的任何成员上递归调用saveload,并写出任何POD成员。 E.g:

class DB_ARRAY : public ISerializable {
public:
    DB* Parent;
    std::string Name;
    std::vector<DB_ROW> Rows;
    DB_ROW * operator[](int);
    DB_ROW * Create();
    DB_ARRAY(DB*,std::string);
    DB_ARRAY();

   virtual std::ostream& save(std::ostream& os) const
   {
       // serialize out members
       return os;
   }

   virtual std::istream& load(std::istream& is)
   {
       // unserialize members
       return os;
   }
};

正如 count0 指出的那样,boost::serialization也是一个很好的起点。

答案 1 :(得分:0)

文件中二进制数据的格式是什么?直到你指定 那,我们不能告诉你如何写它。基本上,你必须指定 所有数据类型的格式(char除外),然后编写代码 逐字节写出该格式(或将其生成缓冲区); 另一方面,逐字节读取它,并重建它。 C ++标准没有说明(或很少)关于大小和 数据类型的表示,除了 sizeof(char)必须是 1,unsigned char必须是纯二进制表示 所有的比特。在我今天可以访问的机器上(Sun Sparc和 PC's),只有字符类型有一个共同的表示。至于 更复杂的类型,值表示中使用的内存 甚至可能不是连续的:一个按位的表示 例如,std::vector通常是三个指针,实际上是 向量中的值完全在其他地方找到。

函数istream::readostream::write是 设计用于将数据读入缓冲区以进行手动解析和写入 预先格式化的缓冲区。你需要使用的事实 reinterpret_cast使用它们应该是一个很好的指示 它不起作用。

相关问题