【问题标题】:Append files to an existing zip file with Poco::Zip使用 Poco::Zip 将文件附加到现有的 zip 文件
【发布时间】:2020-01-16 02:50:54
【问题描述】:

成功压缩文件夹后,我的情况如下:

如果 append = trueoverWrite = false 我必须检查目标 zip 文件是否存在(如果存在)我将检查现有的 zip 文件它不包含哪些文件并将新文件从源文件夹附加到它.

我的问题是:

  • 如何打开 zip 文件并将其放入 compress 对象?或者我应该使用 Poco 中的哪个其他库来打开 zip 流?我正在尝试使用std::ifstream,但 Poco::zip::Compress 似乎没有收到std::ifstream

我当然必须修改 Poco 源代码本身以符合我的要求。提前致谢。

 void ZipFile(string source, string target, List extensions, bool append, bool overWrite)
    {    
        Poco::File tempFile(source);
        if (tempFile.exists())
        {
            if (Poco::File(target).exists() && append && !overWrite) {

            fs::path targetPath = fs::path(target);
            std::ifstream targetFileStream(targetPath.string(), std::ios::binary);

            std::ofstream outStream(target, ios::binary);
            CompressEx compress(outStream, false, false);

            if (tempFile.isDirectory())
            {
                Poco::Path sourceDir(source);
                sourceDir.makeDirectory();
                compress.addRecursive(sourceDir, Poco::Zip::ZipCommon::CompressionMethod::CM_AUTO,
                    Poco::Zip::ZipCommon::CL_NORMAL, false);
            }
            else if (tempFile.isFile())
            {
                Poco::Path path(tempFile.path());
                compress.addFile(path, path.getFileName(), Poco::Zip::ZipCommon::CompressionMethod::CM_AUTO,
                    Poco::Zip::ZipCommon::CL_NORMAL);
            }

            compress.close(); // MUST be done to finalize the Zip file
            outStream.close();
        }
}

【问题讨论】:

    标签: c++ poco-libraries


    【解决方案1】:

    无需修改 Poco 源代码。 Poco 允许您 get the contents of an archiveadd files to it

    首先,打开目标存档以检查其中已经存在哪些文件:

    Poco::ZipArchive archive(targetFileStream);
    

    然后收集您要添加的所有文件,但尚未在存档中:

    std::vector<fs::path> files;
    if (fs::is_directory(source)) {
        for(auto &entry : fs::recursive_directory_iterator())
            // if entry is file and not in zip
            if (fs::is_regular_file(entry)
                && archive.findHeader(fs::relative(entry.path, source)) == archive.headerEnd()) {
                files.push_back(entry.path);
            }
    } else if (fs::is_regular_file(entry)
               && archive.findHeader(source) == archive.headerEnd()) {
        files.push_back(source);
    }
    

    最后,将文件添加到您的 zip 中

    Poco::Zip::ZipManipulator manipulator(target, false);
    for(auto &file : files)
        manipulator.addFile(fs::relative(file, source), file,
                            Poco::Zip::ZipCommon::CompressionMethod::CM_AUTO,
                            Poco::Zip::ZipCommon::CL_NORMAL);
    

    我没有机会对此进行测试。所以尝试一下,看看需要做些什么才能让它发挥作用。

    【讨论】:

    • 谢谢你的帮助,我会试试的。
    • @NguyễnĐứcTâm 顺便说一句。如果您想在overWrite 为真时使用相同的解决方案,您可以使用ZipManipulator::replace
    • @NguyễnĐứcTâm 没有 ab 错误消息,没有人能够帮助您。你必须自己修复它。
    • @NguyễnĐứcTâm 是的,fs::relative 不是实验性文件系统 TS 的一部分,仅适用于 C++17 及更高版本。如果您选择不从路径中删除 source,您的 zip 将看起来像 zip:/source/foo/bar 而不是 zip:/foo/bar。如果这不是问题,只需省略fs::relative。如果是,请使用string::substrstring::find 等经典字符串操作删除file 路径的第一个目录。
    • @NguyễnĐứcTâm 对于手动修改字符串,您可能希望先使用fs::canonical 获取sourcefile 的绝对路径,然后从file 中删除公共前缀。跨度>
    猜你喜欢
    • 2011-01-14
    • 1970-01-01
    • 1970-01-01
    • 2020-01-21
    • 1970-01-01
    • 2013-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多