【问题标题】:Write memory buffer to Zip without copies using Chilkat使用 Chilkat 将内存缓冲区写入 Zip 而不使用副本
【发布时间】:2019-03-29 19:47:44
【问题描述】:

我正在研究 Chilkat Zip library 以将二进制数据转储到磁盘以供以后重用。我要转储的 blob 可能非常大(10+ GiB),因此复制其中任何一个都是浪费时间和空间。

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

我用来测试的sn-p:

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 将 Blob 写入 Zip 文件时避免复制它们?
  • 另外,CkByteData::borrowData only works for inputting data 到 Chilkat,它不会允许 Chilkat 将数据输出回应用程序。那么即使在写入时消除了所有副本,是否有可能在读取文件时也避免副本
  • 如果复制是不可避免的,是否有任何可扩展的解决方法将复制的字节限制为数据的一部分(例如,重复地将部分 blob 添加到 Zip 并将其写入文件)?

注意:我实际上不需要压缩数据(但这是一个不错的优点)。因此,如果解决方案需要禁用压缩,那很好。

【问题讨论】:

    标签: c++ chilkat


    【解决方案1】:

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

    【讨论】:

    • 感谢您的回答。我的问题实际上并不是向 Zip 添加大文件,而是添加由我的应用程序生成的二进制数据。我有一个巨大的二进制数据缓冲区,并希望将其移动到 Zip 中的新文件而不制作任何副本。我没有看到任何使用 Chilkat 库的方法,但也许我忽略了一些聪明的解决方法?
    猜你喜欢
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    相关资源
    最近更新 更多