簡體   English   中英

C ++將多個對象序列化為一個文件,並反序列化有限數量的對象

[英]C++ serialize multiple objects to one file and deserialize limited number of them

在開始之前,請考慮以下代碼:

一個數據傳輸對象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並在以后讀取它。

Supose我生成了30GB的隨機ObjectDTO並將其保存到同一個文件中

我如何只閱讀其中一些以避免達到內存限制?

我正在使用Boost Serialization,因為它是我找到解決第一個問題的簡單方法, 但如果有必要我可以改為任何其他方法!

使用Google協議緩沖區,有用於序列化的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數組的++問題writereadofstreamifstream分別。

我的OutputStreamService writeObjectsToFile結束如下:

void OutputStreamService::writeObjectssToFile(ObjectDTO * objects, int filename){
        ofstream outputFileStream(to_string(filename), std::ios::binary);
        outputFileStream.write((char *)&objects, sizeof(objects));
}

和帶有readObjects的InputStreamService:

ObjectDTO * InputStreamService::readObjects() {
    ifstream inputFileStream(to_string(fileNumber++), std::ios::binary);
    ObjectDTO objects[10];
    inputFileStream.read((char *)&objects, sizeof(objects));
    return objects;
}

這樣我可以定義10或任何其他整數作為我想要讀入的對象的數量。

為了解決mais問題,我現在可以計算我的內存可以處理的對象的aprox數量,然后限制讀取次數!

泰!

暫無
暫無

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

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