C ++ Boost和Lzma解压缩

时间:2018-04-27 23:44:08

标签: c++ boost compression lzma

我正在尝试使用

解压缩.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)

  

警告:GDB:设置控制终端失败:不允许操作   在抛出&#39; boost :: exception_detail :: clone_impl&gt;&#39;的实例后终止调用     what():lzma错误:iostream错误

我试过没有运气使用filtering_streambuf过滤器,其中一段代码与gzip示例的代码非常相似

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

但是我能够解压缩用gzip压缩的文件和上面的代码。 似乎问题仅限于LZMA算法。

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

谢谢

2 个答案:

答案 0 :(得分: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都链接到完全相同的库版本,因此此时版本问题似乎不太可能:

enter image description here

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

答案 1 :(得分:2)

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

起初,我遇到了与上述相同的问题,但是经过一番研究,我发现这是因为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)。