SharpCompress & LZMA2 7z 存档 - 特定文件的提取速度非常慢。为什么?备择方案?
SharpCompress & LZMA2 7z archive - very slow extraction of specific file. Why? Alternatives?
我有一个使用 LZMA2 压缩(压缩级别:超)创建的 7zip 存档。
该档案包含 1,749 个文件,最初总大小为 661mb。
压缩文件大小为 39mb。
现在我正在尝试使用 C# 从该存档中提取一个很小的(大约 200kb)单个文件。
我正在从 IArchive 获取相应的 IArchiveEntry(工作速度相对较快),
但随后调用 IArchiveEntry.WriteToFile(targetPath) 大约需要 33 秒!如果我改为写入内存流,时间也同样长。 (编辑:当我运行在压缩级别为正常的 7z LZMA2 存档上使用它时,它仍然需要 9 秒)
当我在实际的 7zip 应用程序中打开相同的存档并从那里提取相同的文件时,只需要大约 2-3 秒。
我怀疑它是某种多核 (7zip) 与单核 (SharpCompress 可能?) 的事情,但我没有注意到在使用 7zip 解压缩期间出现任何 CPU 使用高峰。也许它太快而无法引起注意。
有谁知道 SharpCompress 如此慢的速度可能是什么问题?我是否可能遗漏了某些设置或使用了错误的工厂 (ArchiveFactory)?
如果没有 - 是否有任何 C# 库可以更快地解压它?
作为参考,下面是我如何使用 SharpCompress 提取的草图:
private void Extract()
{
using(var archive = GetArchive())
{
var entryPath = /* ... path to entry .. */
var entry = TryGetEntry(archive, entryPath);
entry.WriteToFile(some_target_path);
}
}
private IArchive GetArchive()
{
string path = /* .. path to my .7z file */;
return ArchiveFactory.Open(path);
}
private IArchiveEntry TryGetEntry(IArchive archive, string path)
{
path = path.Replace("\", "/");
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
if (entry.Key == path)
return entry;
}
}
return null;
}
更新:作为临时解决方案,我现在将 7zip SDK 中的 7zr.exe 包含在我的应用程序中,并在新进程中 运行 提取单个文件,读取将输出处理成二进制流。
与 SharpCompress 的 ~33 秒相比,这大约需要 3 秒。目前可以使用,但有点难看..所以仍然很好奇为什么 SharpCompress 在那里看起来这么慢
这一行就是问题所在
foreach (var entry in archive.Entries)
问题描述here(即如果有100个文件,解压第一个文件100次,第二个文件99次,以此类推)
您需要使用 reader(仅向前)。见 API.
但是那里的示例代码不支持 7z。
对于 7z,您可以使用 archive.ExtractAllEntries()
,例如
var reader = archive.ExtractAllEntries();
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
reader.WriteEntryToDirectory(extractDir, new ExtractionOptions() { ExtractFullPath = false, Overwrite = true });
}
会快很多。
如果您需要所有文件,您也可以这样做:
using var reader = archive.ExtractAllEntries();
reader.WriteAllToDirectory(targetPath, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true });
我有一个使用 LZMA2 压缩(压缩级别:超)创建的 7zip 存档。 该档案包含 1,749 个文件,最初总大小为 661mb。 压缩文件大小为 39mb。
现在我正在尝试使用 C# 从该存档中提取一个很小的(大约 200kb)单个文件。
我正在从 IArchive 获取相应的 IArchiveEntry(工作速度相对较快), 但随后调用 IArchiveEntry.WriteToFile(targetPath) 大约需要 33 秒!如果我改为写入内存流,时间也同样长。 (编辑:当我运行在压缩级别为正常的 7z LZMA2 存档上使用它时,它仍然需要 9 秒)
当我在实际的 7zip 应用程序中打开相同的存档并从那里提取相同的文件时,只需要大约 2-3 秒。 我怀疑它是某种多核 (7zip) 与单核 (SharpCompress 可能?) 的事情,但我没有注意到在使用 7zip 解压缩期间出现任何 CPU 使用高峰。也许它太快而无法引起注意。
有谁知道 SharpCompress 如此慢的速度可能是什么问题?我是否可能遗漏了某些设置或使用了错误的工厂 (ArchiveFactory)?
如果没有 - 是否有任何 C# 库可以更快地解压它?
作为参考,下面是我如何使用 SharpCompress 提取的草图:
private void Extract()
{
using(var archive = GetArchive())
{
var entryPath = /* ... path to entry .. */
var entry = TryGetEntry(archive, entryPath);
entry.WriteToFile(some_target_path);
}
}
private IArchive GetArchive()
{
string path = /* .. path to my .7z file */;
return ArchiveFactory.Open(path);
}
private IArchiveEntry TryGetEntry(IArchive archive, string path)
{
path = path.Replace("\", "/");
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
if (entry.Key == path)
return entry;
}
}
return null;
}
更新:作为临时解决方案,我现在将 7zip SDK 中的 7zr.exe 包含在我的应用程序中,并在新进程中 运行 提取单个文件,读取将输出处理成二进制流。 与 SharpCompress 的 ~33 秒相比,这大约需要 3 秒。目前可以使用,但有点难看..所以仍然很好奇为什么 SharpCompress 在那里看起来这么慢
这一行就是问题所在
foreach (var entry in archive.Entries)
问题描述here(即如果有100个文件,解压第一个文件100次,第二个文件99次,以此类推)
您需要使用 reader(仅向前)。见 API.
但是那里的示例代码不支持 7z。
对于 7z,您可以使用 archive.ExtractAllEntries()
,例如
var reader = archive.ExtractAllEntries();
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
reader.WriteEntryToDirectory(extractDir, new ExtractionOptions() { ExtractFullPath = false, Overwrite = true });
}
会快很多。
如果您需要所有文件,您也可以这样做:
using var reader = archive.ExtractAllEntries();
reader.WriteAllToDirectory(targetPath, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true });