gpt4 book ai didi

c++ - 使用 boost iostreams 读取和写入数组到压缩文件

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:43:16 37 4
gpt4 key购买 nike

我想将一个数组写入一个文件,边写边压缩它。

稍后,我想从该文件中读取数组,边解压边解压。

Boost 的 Iostream 似乎是一个不错的选择,所以我构建了以下代码。不幸的是,输出和输入数据最后比较不相等。但他们几乎做到了:

Output         Input
0.8401877284 0.8401880264
0.3943829238 0.3943830132
0.7830992341 0.7830989957
0.7984400392 0.7984399796
0.9116473794 0.9116470218
0.1975513697 0.1975509971
0.3352227509 0.3352229893

这表明每个 float 的最低有效字节正在发生变化,或者发生了一些变化。但是,压缩应该是无损的,因此这不是预期或期望的。给了什么?

//Compile with: g++ test.cpp --std=c++11 -lz -lboost_iostreams
#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/zlib.hpp>
#include <cstdlib>
#include <vector>
#include <iomanip>

int main()
{
using namespace std;
using namespace boost::iostreams;

const int NUM = 10000;

std::vector<float> data_out;
std::vector<float> data_in;
data_in.resize(NUM);
for(float i=0;i<NUM;i++)
data_out.push_back(rand()/(float)RAND_MAX);

{
ofstream file("/z/hello.z", ios_base::out | ios_base::binary);
filtering_ostream out;
out.push(zlib_compressor());
out.push(file);

for(const auto d: data_out)
out<<d;
}

{
ifstream file_in("hello.z", ios_base::in | ios_base::binary);
filtering_istream in;
in.push(zlib_decompressor());
in.push(file_in);

for(float i=0;i<NUM;i++)
in>>data_in[i];
}

bool all_good=true;
for(int i=0;i<NUM;i++){
cout<<std::setprecision(10)<<data_out[i]<<" "<<data_in[i]<<endl;
all_good &= (data_out[i]==data_in[i]);
}

cout<<"Good? "<<(int)all_good<<endl;
}

而且,是的,我非常喜欢按照我的方式使用流运算符,而不是一次推或拉整个 vector block 。

最佳答案

问题不在于压缩,而在于序列化 vector 值的方式。

如果您禁用压缩并将大小限制为 10 个元素以便于检查,您可以看到生成的文件如下所示:

0.001251260.5635850.1933040.808740.5850090.4798730.3502910.8959620.822840.746605

如您所见,数字以文本形式表示,小数位数有限,并且没有分隔符。纯属偶然(因为您只使用 < 1.0 的值)您的程序能够产生遥感结果。

发生这种情况是因为您使用了 stream operator << 它将数字类型格式化为文本。


最简单的解决方案似乎是使用 boost::serialization 来处理读取和写入(并使用 boost::iostreams 作为底层压缩流)。我使用了二进制存档,但您也可以使用文本存档(只需将 binary_ 替换为 text_)。

示例代码:

#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/zlib.hpp>

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/vector.hpp>

#include <cstdlib>
#include <vector>
#include <iomanip>

int main()
{
using namespace std;
using namespace boost::iostreams;

const int NUM = 10;

std::vector<float> data_out;
for (float i = 0; i < NUM; i++) {
data_out.push_back(rand() / (float)RAND_MAX);
}

{
ofstream file("hello.z", ios_base::out | ios_base::binary);
filtering_ostream out;
out.push(zlib_compressor());
out.push(file);

boost::archive::binary_oarchive oa(out);
oa & data_out;
}

std::vector<float> data_in;
{
ifstream file_in("hello.z", ios_base::in | ios_base::binary);
filtering_istream in;
in.push(zlib_decompressor());
in.push(file_in);

boost::archive::binary_iarchive ia(in);
ia & data_in;
}

bool all_good=true;
for(int i=0;i<NUM;i++){
cout<<std::setprecision(10)<<data_out[i]<<" "<<data_in[i]<<endl;
all_good &= (data_out[i]==data_in[i]);
}

cout<<"Good? "<<(int)all_good<<endl;
}

控制台输出:

0.001251258887   0.001251258887
0.563585341 0.563585341
0.1933042407 0.1933042407
0.8087404966 0.8087404966
0.5850093365 0.5850093365
0.4798730314 0.4798730314
0.3502914608 0.3502914608
0.8959624171 0.8959624171
0.822840035 0.822840035
0.7466048002 0.7466048002
Good? 1

一个小问题是你没有序列化 vector 的大小,所以在读取时你必须一直读取到流的末尾。

关于c++ - 使用 boost iostreams 读取和写入数组到压缩文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37330645/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com