我正在创建一个类,它存储了许多用于使用boost保存/加载的双精度数。负载需要尽可能快,因此实现二进制格式是目标。
基本上,我有一个存储结构矢量的类:
vector<DataChunk>
其中DataChunk存储一个固定长度的双数组
double data[2048]
当我使用文本存档(text_iarchive)测试功能时,一切都很好。但是,在使用二进制存档时,我会在反序列化类时遇到内存访问冲突。
更奇怪的是,如果我用相同的双精度值填充双数组(即数据的所有元素[2048]等于12345),它就可以工作。然而,不同的双值似乎会使它崩溃(见下文)。
这是我的RawData类:
#pragma once
#include <boost\serialization\vector.hpp>
#include <boost\serialization\array.hpp>
using namespace std;
struct DataChunk
{
public:
double data[2048]; //THIS IS THE PROBLEM AREA
int end;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & data;
ar & end;
}
};
class RawData
{
private:
vector<DataChunk> chunks;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & chunks;
}
public:
void add_chunk(DataChunk chunk){chunks.push_back(chunk);};
vector<DataChunk> get_chunks(){return chunks;};
static void save(RawData rd, string path);
static bool load(RawData & rd, string path);
void add_raw_data(vector<double> raw_data);
vector<double> combine_chunks();
};
我的保存和加载功能如下所示:
void RawData::save(RawData rd, string path)
{
std::ofstream file(path);
if(file.good())
{
boost::archive::binary_oarchive oa(file, std::ios::binary);
//boost::archive::text_oarchive oa(file);
oa << rd;
}
file.flush();
file.close();
}
bool RawData::load(RawData & rd, string path)
{
std::ifstream file(path);
if(file.good())
{
boost::archive::binary_iarchive ia(file, std::ios::binary);
//boost::archive::text_iarchive ia(file);
ia >> rd;
file.close();
return true;
}
else
return false;
}
在我的主要功能中,我测试它是这样的:
string path = "test.data";
RawData old_data;
vector<double> raw_data;
for(int i = 0; i < 5000; i++)
raw_data.push_back(i * 2048); //change this to constant value and it works...
old_data.add_raw_data(raw_data);
//serialize
RawData::save(old_data, path);
//deserialize
RawData new_data;
RawData::load(new_data, path);
//grab the chunks and test the values
vector<DataChunk> chunks_in = new_data.get_chunks();
for(int i = 0; i < chunks_in.size(); i++)
for(int j = 0; j < chunks_in[i].end; j++)
cout<<chunks_in[i].data[j]<<", ";
return 0;
答案 0 :(得分:1)
您需要使用
template <class Archive> void serialize(Archive &ar, unsigned) {
ar & end;
ar & boost::serialization::make_array(data, end);
}
请参阅http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/wrappers.html#arrays
这是演示,自包含:
<强> Live On Coliru 强>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/array.hpp>
struct DataChunk {
public:
double data[2048]; // THIS IS THE PROBLEM AREA
int end;
private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, unsigned) {
ar & end;
ar & boost::serialization::make_array(data, end);
}
};
#include <boost/range.hpp>
#include <boost/range/algorithm.hpp>
class RawData {
private:
std::vector<DataChunk> chunks;
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, unsigned) { ar &chunks; }
public:
void add_chunk(DataChunk chunk) { chunks.push_back(chunk); };
std::vector<DataChunk> get_chunks() { return chunks; };
static void save(RawData rd, std::string path);
static bool load(RawData &rd, std::string path);
void add_raw_data(std::vector<double> raw_data) {
DataChunk chunk;
auto const csize = boost::size(chunk.data);
size_t n = raw_data.size(),
offs = 0ul;
while (n>0) {
auto n_ = std::min(n, csize);
std::copy_n(raw_data.begin() + offs, n_, chunk.data);
chunk.end = n_;
chunks.push_back(chunk);
offs += n_;
n -= n_;
}
}
std::vector<double> combine_chunks() {
std::vector<double> r;
boost::for_each(chunks, [&r](DataChunk const& c) {std::copy_n(c.data, c.end, back_inserter(r));});
return r;
}
};
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <fstream>
void RawData::save(RawData rd, std::string path) {
std::ofstream file(path);
if (file.good()) {
boost::archive::binary_oarchive oa(file, std::ios::binary);
// boost::archive::text_oarchive oa(file);
oa << rd;
}
file.flush();
file.close();
}
bool RawData::load(RawData &rd, std::string path) {
std::ifstream file(path);
if (file.good()) {
boost::archive::binary_iarchive ia(file, std::ios::binary);
// boost::archive::text_iarchive ia(file);
ia >> rd;
file.close();
return true;
} else
return false;
}
#include <iostream>
RawData generate() {
RawData data;
std::vector<double> raw_data;
for (int i = 0; i < 5000; i++)
raw_data.push_back(i * 2048);
data.add_raw_data(raw_data);
return data;
}
int main() {
std::string const path = "test.data";
{
// serialize
RawData const old_data = generate();
RawData::save(old_data, path);
}
{
// deserialize
RawData new_data;
RawData::load(new_data, path);
// grab the chunks and test the values
for (auto d : new_data.combine_chunks())
std::cout << d << ", ";
}
}