使用Chilkat将内存缓冲区写入Zip而不复制

时间:2019-03-28 14:19:01

标签: c++ chilkat

我正在研究Chilkat Zip library,以将二进制数据转储到磁盘以供以后重用。我要转储的Blob可能非常大(超过10个GiB),因此复制这些Blob会浪费时间和空间。

我已经找到了CkByteData::borrowData方法,该方法使我可以让Chilkat使用应用程序分配的缓冲区,而不是将其复制到内部分配的缓冲区中。但是,当将此CkByteData添加到CkZipEntry(使用CkZipEntry::AppendData)时,我注意到我的应用程序突然消耗了两倍的内存;明显的迹象表明Chilkat确实执行了复制。 CkZip::WriteZip之后,内存消耗将恢复正常。

我用于测试的代码段

int main(int, char**)
{
    CkZip zip;
    zip.UnlockComponent(/* hidden */);
    zip.NewZip("data.zip");

    constexpr auto size = 20'000'000; // ~= 20 MiB
    auto data = new char[size];

    for (auto i = 0; i < size; ++i)
       data[i] = static_cast<char>(i);

    CkByteData bd;
    bd.borrowData(data, size);

    auto entry = zip.AppendNew("blob");
    entry->AppendData(bd);
    // --> Memory consumption jumps to ~40 MiB

    delete entry;

    zip.WriteZip();
    // --> Memory consumption drops to ~20 MiB

    delete[] data;
    return 0;
}

我的问题:

  • 使用Chilkat将它们写入Zip文件时,有什么方法避免我的Blob副本
  • 此外,CkByteData::borrowData only works for inputting data属于Chilkat,它将不允许Chilkat将数据输出回应用程序。因此,即使在写入时消除了所有副本,是否有可能在读取文件中的数据时也避免复制
  • 如果不可避免地需要复制,是否有任何可扩展的解决方法,将复制的字节限制为数据的一小部分(例如,将部分Blob重复添加到Zip并将其写入文件)?

注意:实际上,我不需要压缩数据(但这是一个不错的选择)。因此,如果解决方案需要禁用压缩,那就没问题了。

1 个答案:

答案 0 :(得分:1)

如果zip中的新文件可能很大,唯一的解决方案是删除现有条目,然后调用AppendOneFileOrDir来添加新文件。您不想尝试将10GB文件读入内存并添加它。当您调用AppendOneFileOrDir时,它实际上不会将文件读入内存。相反,它创建一个引用文件的zip条目(请参见http://www.chilkatsoft.com/refdoc/csZipEntryRef.html#prop10)。在调用WriteZipAndClose时,要压缩的数据是从文件流式传输的,因此它永远不会完全驻留在内存中。