C++ C++;将多个对象序列化为一个文件,并反序列化有限数量的对象 开始之前,请考虑这个代码:

C++ C++;将多个对象序列化为一个文件,并反序列化有限数量的对象 开始之前,请考虑这个代码:,c++,serialization,boost,vector,boost-serialization,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

一个数据传输对象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;
    }
类ObjectDTO{
公众:
int-id;
弦1;
弦2;
弦3;
国际编码1;
矢量序列表1;
私人:
好友类boost::serialization::access;
模板
无效序列化(存档和存档,常量未签名整数版本){
档案&id;
档案及string1;
档案及资料组2;
档案及资料组3;
档案及编码1;
档案及列表1;
}
系列化

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;
}
void OutputStreamService::writeReportsToFile(向量对象,int文件名){
流输出文件流(到字符串(文件名));
boost::archive::binary_oarchive outputArchive(outputFileStream);
outputArchive>对象;
归还物品;
}
< P>我使用BooSooServices C++系列文库来序列化<代码>向量<代码> <代码> Objutdto < /Cord>s,稍后再阅读。 Supose我生成了30GB的随机
ObjectDTO
s并将其保存到同一个文件中

我怎样才能只读其中的一些,以避免达到内存限制


我之所以使用Boost序列化,是因为这是我发现的解决第一个问题的最简单的方法,但如果需要,我可以改用任何其他方法!

使用谷歌协议缓冲区,有用于序列化的codedOutStream类和用于反序列化的CodedInputStream类

CodedOutputStream方法之一是WriteVarit32,它允许写入一个可以用作流中索引的数字

在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);
反序列化:

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;
}
模板
void TProtoBufSerializer::serialize实现(const T&protoBuf,std::vector&buffer)
{
int-bufLength=protoBuf.ByteSize()+google::protoBuf::io::codedOutStream::VarintSize32(protoBuf.ByteSize());
调整缓冲区大小(bufLength);
google::protobuf::io::ArrayOutputStream arrayOutput(&buffer[0],bufLength);
google::protobuf::io::codedOutput码流codedOutput(&arrayOutput);
codedOutput.WriteVarint32(protoBuf.ByteSize());
protoBuf.SerializeToCodedStream(&codedOutput);
}
模板
bool TProtoBufSerializer::反序列化实现(std::vector和buffer、T和protoBuf)
{
bool反序列化=false;
google::protobuf::io::ArrayInputStream arrayInput(&buffer[0],buffer.size());
google::protobuf::io::CodedInputStream codedInput(&arrayInput);
无符号整数对象大小;
bool header\u readed=codedInput.ReadVarint32(&object\u size);
如果(标题已读取&对象大小>0)
{
if(buffer.size()>=codedInput.CurrentPosition()+对象大小)
{
google::protobuf::io::CodedInputStream::Limit Limit=codedInput.PushLimit(对象大小);
if(protoBuf.ParseFromCodedStream(&codedInput))
{
std::vector::iterator it=buffer.begin();
std::advance(it,codedInput.CurrentPosition());
std::move(it,buffer.end(),buffer.begin());
resize(buffer.size()-codedInput.CurrentPosition());
反序列化=真;
}
其他的
{
抛出TProtoBufSerializerPayloadException();
}
codedInput.PopLimit(极限);
}
}
其他的
{
//标头中使用的varint32最大长度为5字节,
//若给定的缓冲区长度为5字节或更长,且标头仍然无法解码,则引发异常
如果(buffer.size()>=5)
{
抛出TProtoBufSerializerHeaderException();
}
}
返回反序列化;
}

代码> < P>我解决了问题,放弃了Posiple序列化和向量,有利于使用简单的C++代码>写< /COD>和<代码>读<代码> > <流> <代码>和<代码> IFSturi。 我的OutputStreamService WriteObject文件的结尾如下:

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问题,我现在可以计算我的内存可以处理的对象的大约数量,然后限制读取的数量


Ty!

那是什么
[[[]]
[[[[]大小+1]
语法?还有,这到底是做什么的
std::fstream
没有做什么的?很抱歉,我从这里复制并粘贴了它:,fstream正在处理文件,而这是关于(de)的序列化-把文件内容放入C++ ObjutsHeLe@ MarekWaszkiewicz,我最终使用了一个本地方法,但是谢谢你的回答,希望它能帮助其他的观众!你在不同的系统上读文件的地方比你在哪里生成的文件要多?你考虑过内存映射吗?(Boost Interprocess
managed_mapped_file
)@sehe事实并非如此。该程序显示三个选项:创建和保存(随机生成的数据)、搜索和删除。每个选项都必须使用用户提供的分页来完成(在10个文件中保存1000个ObjectDTO,在1000个文件中搜索5个ObjectDTO)。这里的主要问题是,我无法加载整个文件以获得上一个示例中提到的5个ObjectDTO…因为在某些情况下,文件可能会大于内存,您知道吗?我将查看
托管映射文件
无论如何!如果太大而无法放入内存,您如何序列化它。如果您可以序列化它,您可以在原则反序列化在同一个machine@sehe我的错,我误解了你的第一句话。想象一下,我可以在另一台机器上运行这个程序,然后用第一次运行时生成的整个数据库传输它。(这是一个