向IO.Compression.ZipArchiveEntry添加大文件会引发OutOfMemoryException异常。

5

我正在尝试使用以下代码将一个大约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);
                }
            }
        }
    }
}

当调用writer.Write时,我遇到了错误

System.OutOfMemoryException

尽管我使用了一个中间缓冲区,但仍然出现了这个错误...

有什么解决办法吗?


你可以通过移除读取器/写入器并使用stream.copyto来简化代码。但不确定它是否能解决问题。 - CodesInChaos
请查看 AddEntry(name, stream)(在调用 Save 之前不要关闭流)和 AddFile(name, nameInFileSystem) - CodesInChaos
@CodesInChaos:你的意思是使用zipFile.CreateEntryFromFile -> 仍然不起作用。我接受了将CPU架构更改为X64的答案,但在指定ZipArchiveMode.Update时,ZipArchiveEntry的低效值得指出(这会导致将整个zip内容加载到内存中)。 - Pinte Dani
1个回答

2
将应用程序构建为任何CPU并在x64机器上执行它。这应该解决问题。(或直接将应用程序构建为x64)。
视频通常无法压缩很多,而zip文件可能会一直保留在内存中,直到完全创建完成。

有没有类似于浮点数的压缩页面?人们普遍认为只要压缩任何东西,即使你正在压缩已经被压缩过的东西,它也会变得更小,这种信念似乎越来越流行! - user146043
我接受这个答案,现在似乎可以工作了。虽然我要指出IO.Compression.ArchiveEntry类的低效率,当指定“ZipArchiveMode.Update”时需要在内存中加载所有ZipArchive内容。(可怕) 来自msdn: 整个归档的内容都保存在内存中,在归档被处理之前不会将任何数据写入底层文件或流。 msdn - Pinte Dani
这可能是因为在所有数据可用时进行压缩,以提高压缩效率。 - Ignacio Soler Garcia
记得删除临时缓冲区! - Ignacio Soler Garcia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接