c++ - 使用 Chilkat 将内存缓冲区写入 Zip 而不使用副本
问题描述
我正在研究Chilkat Zip 库以将二进制数据转储到磁盘以供以后重用。我要转储的 blob 可能非常大(10+ GiB),因此复制其中任何一个都是浪费时间和空间。
我已经找到了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
仅适用于向 Chilkat 输入数据,它不会允许 Chilkat 将数据输出回应用程序。因此,即使在写入时消除了所有副本,是否也可以在从文件中读取数据时避免副本? - 如果复制是不可避免的,是否有任何可扩展的解决方法将复制的字节限制为数据的一部分(例如,重复地将 blob 的一部分添加到 Zip 并将其写入文件)?
注意:我实际上不需要压缩数据(但这是一个很好的加分项)。因此,如果解决方案需要禁用压缩,那很好。
解决方案
如果 zip 中的新文件可能很大,唯一的解决方案是删除现有条目,然后调用 AppendOneFileOrDir 以添加新文件。您不想尝试将 10GB 文件读入内存并添加它。当您调用 AppendOneFileOrDir 时,它实际上并没有将文件读入内存。相反,它会创建一个引用文件的 zip 条目(请参阅http://www.chilkatsoft.com/refdoc/csZipEntryRef.html#prop10)当调用 WriteZipAndClose 时,要压缩的数据从文件中流式传输,因此它永远不会完全驻留在记忆中。
推荐阅读
- python-3.x - 无法使用带有 python 3.8 的 conda 安装 tensorflow
- rust - Rust lang thread::sleep() 在 Windows 上的游戏循环期间睡眠几乎是指定时间的两倍
- php - 在 XAMPP 上工作时如何使用 VScode 实时服务器?
- android - 将处理程序变量从 MainActivity 类传递到 android kotlin 中的后台线程类的最佳方法是什么?
- javascript - 输入类型数字的正则表达式只需要 10 位数字吗?只接受整数
- bash - Git filter-branch 到 filter-repo :标签未重写
- bootstrap-4 - 模态淡入淡出效果在 Bootstrap 4.1 或更高版本上不起作用
- .htaccess - 如何使用 htaccess 从 url 隐藏文件夹名称?
- python-3.x - Django:在 HTML 中获取与用户相关的字段值
- java - 为什么在使用 for 循环打印金字塔时会得到意外的输出?