C++将多个对象序列化到一个文件并反序列化有限数量的对象

标签 c++ serialization boost vector boost-serialization

开始之前,请考虑以下代码:

一个数据传输对象ObjectDTO

class ObjectDTO {

public:
    int id;
    string string1;
    string string2;
    string string3;
    int code1;
    vector<string> stringList1;

private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive &archive, const unsigned int version) {
        archive & id;
        archive & string1;
        archive & string2;
        archive & string3;
        archive & code1;
        archive & stringList1;
    }

序列化

void OutputStreamService::writeReportsToFile(vector<ObjectDTO> objects, int filename){
    ofstream outputFileStream(to_string(filename));
    boost::archive::binary_oarchive outputArchive(outputFileStream);
    outputArchive << objects;
}

反序列化

vector<ObjectDTO> InputStreamService::readObjects() {
    ifstream inputFileStream(to_string(fileNumber++));
    boost::archive::binary_iarchive inputArchive(inputFileStream);
    vector<ObjectDTO> objects;
    inputArchive >> objects;
    return objects;
}

我正在使用 Boost Serialization C++ 库序列化 ObjectDTOvector 并稍后读回。

假设我生成了 30GB 的随机 ObjectDTO 并将其保存到同一个文件中

我怎样才能只读取其中的一部分以避免达到内存限制?

我正在使用 Boost 序列化,因为这是我发现解决第一个问题的简单方法但如有必要,我可以更改为任何其他方法!

最佳答案

改用谷歌 Protocol Buffer ,有用于序列化的 CodedOutputStream 类和用于反序列化的 CodedInputStream 类。

其中一种 CodedOutputStream 方法是 WriteVarint32,它允许写入一个数字,该数字可用作流中的索引。

在CodeInputStream中有对应的ReadVarint32方法,例如。

序列化:

char text[[]] = "Hello world!";
coded_output->WriteVarint32(strlen(text));
coded_output->WriteRaw(text, strlen(text));

反序列化:

uint32 size;
coded_input->ReadVarint32(&size);

char* text = new char[size + 1];
coded_input->ReadRaw(buffer, size);

最后一行允许您从给定索引开始读取序列化流的内容。

这是我在开始时以给定长度序列化/反序列化流的两种方法。

template < class T>
void TProtoBufSerializer::SerializeImplementation(const T& protoBuf, std::vector<char>& buffer ) 
{
    int bufLength = protoBuf.ByteSize() + google::protobuf::io::CodedOutputStream::VarintSize32(protoBuf.ByteSize());
    buffer.resize(bufLength);

    google::protobuf::io::ArrayOutputStream arrayOutput(&buffer[0], bufLength);
    google::protobuf::io::CodedOutputStream codedOutput(&arrayOutput);

    codedOutput.WriteVarint32(protoBuf.ByteSize());
    protoBuf.SerializeToCodedStream(&codedOutput);     
}

template < class T>
bool TProtoBufSerializer::DeSerializeImplementation(std::vector<char>& buffer, T& protoBuf )
{
   bool deserialized = false;

   google::protobuf::io::ArrayInputStream arrayInput(&buffer[0],buffer.size());
   google::protobuf::io::CodedInputStream codedInput(&arrayInput);

   unsigned int object_size;
   bool header_readed = codedInput.ReadVarint32(&object_size);

   if(header_readed && object_size > 0)
   {
       if( buffer.size() >= codedInput.CurrentPosition() + object_size )
       {
           google::protobuf::io::CodedInputStream::Limit limit = codedInput.PushLimit(object_size);

           if(protoBuf.ParseFromCodedStream(&codedInput))
           {
               std::vector<char>::iterator it = buffer.begin();
               std::advance(it,codedInput.CurrentPosition());
               std::move(it,buffer.end(),buffer.begin() );
               buffer.resize(buffer.size() - codedInput.CurrentPosition());
               deserialized = true;
           }
           else
           {
              throw TProtoBufSerializerPayloadException();
           }
           codedInput.PopLimit(limit);
       }
   }
   else
   {
       //varint32 which is used in header is at the most 5 bytes long, 
       //if given buffer is 5 bytes or more long and header still cannot be decoded - raise exception 
       if(buffer.size() >= 5) 
       {
          throw TProtoBufSerializerHeaderException();
       }
   }
   return deserialized;
}

关于C++将多个对象序列化到一个文件并反序列化有限数量的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36802436/

相关文章:

grails - 呈现为JSON在Grails中不起作用

c++ - boost 序列化 : How To Predict The Size Of The Serialized Result?

c++ - 为什么我不能使用 strerror?

c# - 序列化类型化数据集、更新程序集、反序列化错误

python - DRF 序列化器通过 REST API 与第三方应用程序进行操作

c++ - boost::enable_if_c 错误:不是模板非类型参数的有效类型

C++ - Clutter 1.0 - 从线程调用函数导致段错误

c++ - 使用用户定义的构造函数对非聚合类进行值初始化

c++ - 使用 C 进行套接字编程时无法接收或发送整个数据包

c++ - 如何决定 ADT 中什么是私有(private)的、什么是公共(public)的?