向 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 异常的主要内容,如果未能解决你的问题,请参考以下文章

SPARK的计算向量化-已有的向量化项目

将数组向右而不是向左旋转

前向链接与后向链接

3、Kafka生产者-向Kafka写入数据

Matlab训练多层神经网络

如何向Map中添加数据