我正在研究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;
}
我的问题:
CkByteData::borrowData
only works for inputting data属于Chilkat,它将不允许Chilkat将数据输出回应用程序。因此,即使在写入时消除了所有副本,是否有可能在读取文件中的数据时也避免复制?注意:实际上,我不需要压缩数据(但这是一个不错的选择)。因此,如果解决方案需要禁用压缩,那就没问题了。
答案 0 :(得分:1)
如果zip中的新文件可能很大,唯一的解决方案是删除现有条目,然后调用AppendOneFileOrDir来添加新文件。您不想尝试将10GB文件读入内存并添加它。当您调用AppendOneFileOrDir时,它实际上不会将文件读入内存。相反,它创建一个引用文件的zip条目(请参见http://www.chilkatsoft.com/refdoc/csZipEntryRef.html#prop10)。在调用WriteZipAndClose时,要压缩的数据是从文件流式传输的,因此它永远不会完全驻留在内存中。