【问题标题】:C++ Boost and Lzma decompressionC++ Boost 和 Lzma 解压
【发布时间】:2018-04-27 23:44:07
【问题描述】:

我正在尝试使用

解压缩 .7z(或 .xz 或 .lzma)文件
  • 在 Linux 平台上提升库 1.67.0

使用以下代码:

    vector<T> readFromCompressedFile(string input_file_path, string output_file_path)
    {
    namespace io = boost::iostreams;

    stringstream strstream;

    ifstream file(input_file_path.c_str(), ios_base::in | ios_base::binary);
    ofstream out(output_file_path, ios_base::out | ios_base::binary);

    boost::iostreams::filtering_istream in;
    in.push(io::lzma_decompressor());
    in.push(file);

    io::copy(in, out);

    cout<<strstream.str()<<endl;

代码编译,但我得到了复制方法引发的运行时异常(lzma_error)

warning: GDB: Failed to set controlling terminal: Operation not permitted
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::iostreams::lzma_error> >'
  what():  lzma error: iostream error

我尝试使用与 gzip 示例中的代码非常相似的部分代码的 filtering_streambuf 过滤器,但没有成功

https://www.boost.org/doc/libs/1_67_0/libs/iostreams/doc/classes/gzip.html#examples

但是,我能够解压缩使用 gzip 和上述代码压缩的文件。 看来问题仅限于 LZMA 算法。

有同样问题的人吗?有什么想法吗?

谢谢

【问题讨论】:

    标签: c++ boost compression lzma


    【解决方案1】:

    您的代码很好,这不是错误。

    一开始遇到和上面一样的问题,后来研究了一下发现是因为boost iostreams库调用了XZ库提供的lzma_stream_decoder做解码工作,lzma_stream_decoder不支持.lzma.7z格式文件。如果您尝试使用 boost iostreams 库解码 .lzma.7z 格式文件,则会抛出错误代码为:LZMA_FORMAT_ERROR 的异常。错误码定义请参考XZ源码xz-5.2.4.tar.gz

    \src\liblzma\api\lzma\base.h

    LZMA_FORMAT_ERROR       = 7,
        /**<
         * \brief       File format not recognized
         *
         * The decoder did not recognize the input as supported file
         * format. This error can occur, for example, when trying to
         * decode .lzma format file with lzma_stream_decoder,
         * because lzma_stream_decoder accepts only the .xz format.
         */
    

    并且请参考boost iostreams库的源码:lzma.cpp

    您可以尝试解码 .xz 文件,不会有问题。 我已经使用您在 Windows X64 和 boost 库 1.66.0 上提供的相同代码对此进行了测试。

    顺便说一句,@sehe 提供的错误检测代码具有误导性:

     try {
        io::copy(in, out);
    } catch(io::lzma_error const& e) {
        std::cout << boost::diagnostic_information(e, true);
        std::cout << e.code() << ": " << e.code().message() << "\n";
    }
    

    应该是:

     try {
        io::copy(in, out);
    } catch(io::lzma_error const& e) {
        std::cout << boost::diagnostic_information(e, true);
        std::cout << e.error() << ": " << e.code().message() << "\n";
    }
    

    然后你会发现抛出异常的错误码是:7 (LZMA_FORMAT_ERROR)。

    【讨论】:

    • 非常感谢 - 这不仅仅是扩展程序的问题,xzlzma 是不同的压缩格式。
    【解决方案2】:

    我可以确认同样的问题。

    使用其他工具解压lzma文件没问题。可能存在版本控制问题,或者可能存在错误。这是代码的清理版本,没有那么多噪音,消除了一些可疑的风格(using namespace std)并尝试获取更多错误信息:

    #include <boost/iostreams/copy.hpp>
    #include <boost/iostreams/filter/lzma.hpp>
    #include <boost/iostreams/filtering_stream.hpp>
    #include <boost/exception/diagnostic_information.hpp>
    #include <fstream>
    #include <iostream>
    
    namespace io = boost::iostreams;
    
    void foo(std::string input_file_path, std::string output_file_path) {
        namespace io = boost::iostreams;
    
        std::ifstream file(input_file_path, std::ios::binary);
        std::ofstream out(output_file_path, std::ios::binary);
    
        boost::iostreams::filtering_istreambuf in;
        in.push(io::lzma_decompressor());
        in.push(file);
    
        try {
            io::copy(in, out);
        } catch(io::lzma_error const& e) {
            std::cout << boost::diagnostic_information(e, true);
            std::cout << e.code() << ": " << e.code().message() << "\n";
        } catch(boost::exception const& e) {
            std::cout << boost::diagnostic_information(e, true);
        }
    }
    
    int main() {
        foo("test.cpp.lzma", "output.txt");
    }
    

    在我的系统上,我已验证测试程序和 /usr/bin/lzma 都链接到完全相同版本的库,因此在这一点上似乎不太可能出现版本控制问题:

    我认为应该向上游报告问题(在boost Trac、邮件列表或github issue

    【讨论】:

      猜你喜欢
      • 2011-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多