libarchive在某些条目上返回错误,而7z可以正常提取

时间:2018-04-07 00:51:58

标签: c++ 7zip libarchive

我在libarchive版本3.3.2遇到问题。我写了一个程序来读取7z档案中的选定条目,如下所示:

file.7z
    |__ file.xml
    |__ file.fog
    |__ file_1.fog

但是,对于我的大多数档案,该程序无法阅读file_1.fog,而有些人无法阅读file.fog。我尝试使用archive_error_string()查看发生了什么,错误是corrupted archivetruncated RAR archiveDecompressing internal error

这是一个存档sample和问题代码:

void list_archive(string name) {
    struct archive *a;
    struct archive_entry *entry;

    // create new archive struct for the file
    a = archive_read_new();
    archive_read_support_filter_all(a);
    archive_read_support_format_all(a);

    // open 7z file
    int r = archive_read_open_filename(a, name.c_str(), 1024);

    if (r != ARCHIVE_OK) {
        cout << "cannot read file: " << name << endl;
        cout << "read error: " << archive_error_string(a) << endl;
    }

    // looping through entries
    for (;;) {
        int status = archive_read_next_header(a, &entry);

        // if there's no more header
        if (status != ARCHIVE_OK) break;

        // print some status messages to stdout
        string pathname(archive_entry_pathname(entry));
        cout << "working on: " << pathname << endl;

        size_t entry_size = archive_entry_size(entry);

        // load the entry's content
        char * content;
        content = (char*)malloc(entry_size);
        r = archive_read_data(a, content, entry_size);

        // check if archive_read_data was successful
        if (r > 0) {
            cout << "read " << r << " of " << entry_size << " bytes successfully\n";
            // we are interested in .fog file only
            if (pathname.back() == 'g') {
                // do something with the .fog file
            }
        }
        else // usually the error happens here
            if (archive_errno(a) != ARCHIVE_OK) cout << "read error: " << archive_error_string(a) << endl;


        // free the content and clear the entry
        archive_read_data_skip(a);
        free(content);
        archive_entry_clear(entry);

        cout << "-----" << endl;
    }

    // we are done with the current archive, free it
    r = archive_read_free(a);
    if (r != ARCHIVE_OK) {
        cout << "Failed to free archive object. Error: " << archive_error_string(a) << endl;
        exit(1);
    }
}

2 个答案:

答案 0 :(得分:0)

如果未来的用户遇到同样的问题,我找到了麻烦制造者并在此回答。

int r = archive_read_open_filename(a, name.c_str(), 1024);

显然1024对于缓冲区大小来说太小了。我把它增加到102400并且能够读取/提取我的所有档案。

答案 1 :(得分:0)

请注意,技术上缓冲区大小不应该破坏功能,降低速度是可以的,但破坏操作是不可接受的,因此我认为它处理档案的方式不是那么可靠。