【问题标题】:C++ - Read .gz file, uncompress it and write to another fileC++ - 读取 .gz 文件,解压缩并写入另一个文件
【发布时间】:2025-12-16 16:40:01
【问题描述】:

我正在做一个需要读取文件的项目。这些文件可以是未压缩的或压缩的(.gz 扩展名)。

我已经设法将我的项目设置为利用 zlib 和 boost::iostreams 来执行解压缩,但我无法正确处理 std::istream 形式的解压缩文件。

让我更清楚: 我正在编写的方法将文件的路径作为输入,并且读取文件的逻辑在 std::ifstream 对象类型上完成。如果文件是未压缩的,我没问题,但是压缩时会出现问题。 根据 boost 网站的在线文档,我正在做这样的事情

//Read from the first command line argument, assume it's gzipped
std::ifstream file(filename, std::ios_base::in | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::input> inbuf;
inbuf.push(boost::iostreams::gzip_decompressor());
inbuf.push(file);
//Convert streambuf to istream
std::istream instream(&inbuf);

问题是我想为未压缩文件创建一个std::ifstream,但获得未压缩文件的唯一方法是std::istream(sn-p 的最后一行)。因为我的处理逻辑需要 std::ifstream,所以我试图弄清楚如何从 istream 获取 ifstream,但到目前为止我还没有找到有用的资源。

重写逻辑来处理不同的输入类型不是我想要的目标,所以我问你是否对这个主题有任何提示。

感谢任何帮助/资源!

谢谢

【问题讨论】:

    标签: c++ boost zlib ifstream istream


    【解决方案1】:

    如果您需要文件流,请将其设为文件。

    我认为需要ifstream&amp; 而不是istream&amp; 的API 可能是错误的,因为很少有理由假设您的istream&amp; - ifstreamistringstream 等都可以通过就好了。

    只要 API 是这样的,你就需要一个文件:

    Live On Coliru

    #include <boost/iostreams/filter/gzip.hpp>
    #include <boost/iostreams/filtering_streambuf.hpp>
    #include <boost/iostreams/copy.hpp>
    #include <fstream>
    
    namespace io = boost::iostreams;
    
    int main(int argc, char** argv) {
        assert(argc>1);
        // Read from the first command line argument, assume it's gzipped
        std::ifstream file(argv[1], std::ios::binary);
        io::filtering_istreambuf inbuf;
        inbuf.push(io::gzip_decompressor());
        inbuf.push(file);
    
        // Convert streambuf to istream
        {
            std::ofstream ofs("temp.dat", std::ios::binary);
            io::copy(inbuf, ofs);
        }
        std::ifstream instream("temp.dat");
    }
    

    试运行

    g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp -lboost_iostreams
    gzip -k main.cpp
    ./a.out main.cpp.gz
    md5sum temp.dat main.cpp
    

    打印

    6e2d99a75e7f637e9c07e9c78acb04f4  temp.dat
    6e2d99a75e7f637e9c07e9c78acb04f4  main.cpp
    

    【讨论】: