2014-01-24 16 views
1

我有下面的结构再次反序列化它:结构序列化到文件,并用绳子

struct ArchiveTableEntry 
     { 
      uint32_t id; 
      char filename[MAX_FILENAME_LEN + 1]; 
      uint32_t filename_crc32; 
      uint32_t real_data_size; 
      uint32_t block_data_size; 

      uint32_t data_crc32; 
      char data_md5_checksum[16]; 

      uint64_t data_offset; 
      uint8_t flag; 
     }; 

和它系列化后,我有很好的输出到文件。 也从文件加载属性也。 我用的memcpy进行序列化/反序列化,而现在我的问题是:我如何可以替换字符的文件名[MAX_FILENAME_LEN + 1];由std :: string,并保持序列化/反序列化与保存未使用字节char char浪费。 谢谢!

+0

'struct'字段可能是内存对齐填充的基础...使用适当的序列化机制来获得大小有效的输出(例如google protobuf)。 –

回答

1

尽量避免使用的memcpy-ING为序列化的指针..相反,利用流..你甚至可以使该序列化任何类型的数据流类。接下来,您只需要添加< <和>>运算到需要被序列化的任何类。

#include <iostream> 
#include <fstream> 
#include <string> 
#include <cstring> 

struct ArchiveTableEntry 
{ 
    uint32_t id; 
    std::string filename; 
    uint32_t filename_crc32; 
    uint32_t real_data_size; 
    uint32_t block_data_size; 

    uint32_t data_crc32; 
    char data_md5_checksum[16]; 

    uint64_t data_offset; 
    uint8_t flag; 
}; 

std::ostream& operator << (std::ostream& os, const ArchiveTableEntry entry) 
{ 
    return os << entry.id << entry.filename.size() << entry.filename 
       << entry.filename_crc32 << entry.real_data_size << entry.block_data_size 
       << entry.data_crc32 << entry.data_md5_checksum << entry.data_offset << entry.flag; 
} 

std::istream& operator >> (std::istream& os, ArchiveTableEntry& entry) 
{ 
    std::size_t filesize = 0; 
    os >> entry.id; 
    os >> filesize; 
    entry.filename.resize(filesize); 
    os.read(&entry.filename[0], filesize); 
    os >> entry.filename_crc32 >> entry.real_data_size >> entry.block_data_size >> entry.data_crc32; 
    os >> entry.data_md5_checksum >> entry.data_offset >> entry.flag; 
    return os; 
} 



int main() 
{ 
    const char* md5_checksum = "some checksum"; 

    ArchiveTableEntry data; 
    data.id = 1; 
    data.filename = "file.txt"; 
    data.filename_crc32 = 10434235; 
    data.real_data_size = 1024; 
    data.block_data_size = 256; 
    data.data_crc32 = 324225252; 
    data.data_md5_checksum = 1; 

    std::memset(data.data_md5_checksum, 0, sizeof(data.data_md5_checksum)/sizeof(char)); 
    strcpy(data.data_md5_checksum, md5_checksum); 

    data.data_offset = 512; 
    data.flag = 1; 

    std::fstream out("C:/Users/School/Desktop/Test.bin", std::ios::out); 
    if (out.is_open()) 
    { 
     out << data; 
     out.close(); 
    } 

    std::fstream in("C:/Users/School/Desktop/Test.bin", std::ios::in); 
    if (in.is_open()) 
    { 
     in >> data; 
     in.close(); 
    } 

    std::cout<<data.id<<" "<<data.filename<<" "<<data.filename_crc32<<" "<<data.real_data_size<<" "<<data.block_data_size<<" "; 
    std::cout<<data.data_crc32<<" "<<data.data_md5_checksum<<" "; 
} 
+0

“尽量避免使用的memcpy-ING为序列化的指针。”是的,如果你讨厌表演。 – Tara

+0

大声笑.. OP是创建一个缓冲区,将所有内容复制到缓冲区,并书面的文件。其次,他不能memcpy一个'std :: string',这是他的首要问题。他没有将字符串的长度写入文件,然后写入内容。使用流,他不必复制到临时缓冲区,然后写入文件。当使用其他标准库类时,它也使他的生活更轻松。 – Brandon

+0

你对std :: string部分是对的。但通常你使用可以一次读/写的结构来进行序列化/反序列化。这通常比多个小型读/写操作更快。 – Tara