向 IO.Compression.ZipArchiveEntry 添加大文件会引发 OutOfMemoryException 异常
Posted
技术标签:
【中文标题】向 IO.Compression.ZipArchiveEntry 添加大文件会引发 OutOfMemoryException 异常【英文标题】:Adding large files to IO.Compression.ZipArchiveEntry throws OutOfMemoryException Exception 【发布时间】:2015-02-06 07:37:28 【问题描述】:我正在尝试使用以下代码将大型视频文件(~500MB)添加到 ArchiveEntry:
using (var zipFile = ZipFile.Open(outputZipFile, ZipArchiveMode.Update))
var zipEntry = zipFile.CreateEntry("largeVideoFile.avi");
using (var writer = new BinaryWriter(zipEntry.Open()))
using (FileStream fs = File.Open(@"largeVideoFile.avi", FileMode.Open))
var buffer = new byte[16 * 1024];
using (var data = new BinaryReader(fs))
int read;
while ((read = data.Read(buffer, 0, buffer.Length)) > 0)
writer.Write(buffer, 0, read);
我收到了错误
System.OutOfMemoryException
当 writer.Write 被调用时,我以为我使用了一个中间缓冲区......
知道如何解决这个问题吗?
【问题讨论】:
您可以通过删除读取器/写入器并使用 stream.copyto 来简化代码。怀疑它解决了问题。 看看AddEntry(name, stream)
(在调用Save
之前不要关闭流)和AddFile(name, nameInFileSystem)
@CodesInChaos:你的意思是使用zipFile.CreateEntryFromFile
-> 仍然不起作用。我接受了将 CPU 架构更改为 X64 的答案,但是当指定 ZipArchiveMode.Update
时,ZipArchiveEntry 的低效率值得指出(这会导致将 zip 的全部内容加载到内存中)
【参考方案1】:
像任何 CPU 一样构建应用程序并在 x64 机器上执行它。这应该可以解决问题。 (或直接将应用程序构建为 x64)。
视频通常不能被大量压缩,并且 zip 文件可能会保留在内存中,直到完全创建为止。
【讨论】:
是否有类似于浮点的压缩页面?即使您正在压缩已经压缩的东西,只要压缩任何东西都会使其更小,这种信念似乎变得越来越流行! 我接受这个作为答案,现在似乎可以工作了。虽然我会指出 IO.Compression.ArchiveEntry 类的效率低下,当指定“ZipArchiveMode.Update”时,它需要加载内存中的所有 ZipArchive 内容。 (可怕)来自 msdn :整个存档的内容保存在内存中,在处理存档之前,不会将数据写入基础文件或流。 msdn 这可能是因为在所有数据可用时才进行压缩以提高压缩效率。 记得删除临时缓冲区的东西!以上是关于向 IO.Compression.ZipArchiveEntry 添加大文件会引发 OutOfMemoryException 异常的主要内容,如果未能解决你的问题,请参考以下文章