Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用boost iostreams将阵列读写到压缩文件_C++_Boost_Compression_Boost Iostreams - Fatal编程技术网

C++ 使用boost iostreams将阵列读写到压缩文件

C++ 使用boost iostreams将阵列读写到压缩文件,c++,boost,compression,boost-iostreams,C++,Boost,Compression,Boost Iostreams,我想将一个数组写入一个文件,在运行时对其进行压缩 稍后,我想从该文件中读取数组,并在运行时对其进行解压缩 Boost的Iostreams似乎是一个很好的方法,因此我构建了以下代码。不幸的是,输出和输入数据在最后并不相等。但他们几乎做到了: Output Input 0.8401877284 0.8401880264 0.3943829238 0.3943830132 0.7830992341 0.7830989957 0.7984400392 0.79843997

我想将一个数组写入一个文件,在运行时对其进行压缩

稍后,我想从该文件中读取数组,并在运行时对其进行解压缩

Boost的Iostreams似乎是一个很好的方法,因此我构建了以下代码。不幸的是,输出和输入数据在最后并不相等。但他们几乎做到了:

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
这表明每个浮点数的最低有效字节正在被更改,或者其他什么。但是,压缩应该是无损的,因此这不是预期的或期望的。有什么好处

//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;
}
//使用:g++test.cpp--std=c++11-lz-lboost\u iostreams编译
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main()
{
使用名称空间std;
使用名称空间boost::iostreams;
常数int NUM=10000;
std::矢量数据输出;
std::矢量数据输入;
调整数据大小(NUM);

对于(float i=0;i而言,问题不在于压缩,而在于序列化向量值的方式

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

0.001251260.5635850.1933040.808740.5850090.4798730.3502910.8959620.822840.746605
正如您所看到的,数字以文本形式表示,小数位数有限,并且没有分隔符。您的程序能够产生一个远程可感知的结果完全是偶然的(因为您只处理<1.0的值)

这是因为您使用了将数字类型格式化为文本的


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

示例代码:

#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;
}


一个小问题是,您没有序列化向量的大小,因此在读取时,您必须一直读取到流的末尾。

正如Dan Mašek在中指出的那样,
当您将压缩排除在样本之外时,是否也会出现问题?是的,它会出现,只是尝试了一下。您正在将浮点数作为字符串打印到文件中。A没有分隔符的lso。只有通过保存小于1的值,您才能获得远程感知的内容,因为否则它将是不可解析的。我不认为不需要分隔符来进行压缩/解压缩:我猜想(可能是错误的)当有足够的数据可用时,浮点数被推入内部字节缓冲区并进行压缩。解压的工作原理类似:数据被读取到内部缓冲区,并在有足够的信息可用时从内部缓冲区中取出。换句话说,无压缩的打印会使边界的位置模糊不清因为4字节浮点由输出中的可变字节数表示。压缩时不会出现歧义,因为读/写操作一直持续到翻译了4个字节的数据。如果您将其存储为文本,则会出现歧义,除非这不是您想要的,或者您希望使用一致的数字将其打印为文本字符数(但是您可能需要与默认的
运算符>>
不同的内容来读取它)谢谢你,丹。你敏锐的观察足以让我弄明白其他的一切。我不知道为什么我只是出于好奇而期待
,你是基于什么得出使用boost::serialization会使内存需求翻倍的结论的?据我所知,它会像你一样写入底层流。如果有的话ng,使用zlib对内存占用的影响将更加显著(对于其所有内部数据结构).我的错,我已经有一段时间没有使用序列化了。当我这样做时,序列化表示需要保存在内存中,这使要求增加了一倍。我想可能有一种方法可以以流式方式使用序列化。我不再使用Boost序列化,而是使用grane来减少依赖性和提高速度()。
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
#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(233*(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);

      char *dptr = reinterpret_cast<char*>(data_out.data());

      for(int i=0;i<sizeof(float)*NUM;i++)
        out.write(&dptr[i],1);
    }

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

      char *dptr = reinterpret_cast<char*>(data_in.data());

      for(int i=0;i<sizeof(float)*NUM;i++)
        in.read(&dptr[i],1);
    }

    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;
}