簡體   English   中英

C ++二進制文件讀取

[英]C++ Binary file reading

我試圖將包括對象矢量在內的對象保存在二進制文件中。

這是文件代碼的一些負擔:

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函數的第一個參數將具有正確的值,並且該對象上的向量Array具有正確的大小。但是,如果我從obj-> Arrays中索引了任何對象的任何值,它將引發訪問沖突異常。

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

后者總是打印相同的地址,所以當我保存一個強制轉換為char *的對象時,它也保存了它的地址嗎?

正如各種評論者指出的那樣,您不能簡單地通過保存/恢復對象的內存來序列化(非POD)對象。

實現序列化的通常方法是在類上實現序列化接口。 像這樣:

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

然后,您可以在可序列化的類中實現此接口,以遞歸的方式在引用其他可序列化的類的任何成員上調用saveload ,並寫出任何POD成員。 例如:

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也是一個很好的起點。

文件中二進制數據的格式是什么? 除非您指定,否則我們不會告訴您如何編寫。 基本上,您必須為所有數據類型指定格式( char除外),然后編寫代碼以逐字節寫出該格式(或將其生成到緩沖區中); 另一方面,逐字節讀取並重建它。 C ++標准對數據類型的大小和表示沒有任何(或很少)說明, 只是 sizeof(char)必須為1,並且unsigned char必須為所有位的純二進制表示。 在我今天可以訪問的計算機(Sun Sparc和PC)上,只有字符類型具有相同的表示形式。 對於更復雜的類型,值表示形式中使用的內存甚至可能不是連續的:例如, std::vector的按位表示形式通常是三個指針,向量中的實際值完全可以在其他地方找到。

istream::readostream::write函數旨在將數據讀入緩沖區以進行手動解析,並寫入預格式化的緩沖區。 您需要使用reinterpret_cast否則才能使用它們,這充分表明它不起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM