开始之前,请考虑以下代码:
一个数据传输对象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++ 库序列化 ObjectDTO
的 vector
并稍后读回。
假设我生成了 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/