.net ZipArchive无法使用MemoryStream正确压缩文件

.net ZipArchive无法使用MemoryStream正确压缩文件,.net,compression,zip,.net,Compression,Zip,我正在使用.NET 4.5中的ZipArchive,它可以正确地与FileStream一起工作: 但是,如果我试图使用MemoryStream压缩文件,它将返回无法打开的字节数组并保存到磁盘: public static byte[] CompressInMemory(string dir) { var files = Directory.GetFiles(dir); byte[] result = null; using (var stream = new Memory

我正在使用.NET 4.5中的ZipArchive,它可以正确地与FileStream一起工作:

但是,如果我试图使用MemoryStream压缩文件,它将返回无法打开的字节数组并保存到磁盘:

public static byte[] CompressInMemory(string dir)
{
    var files = Directory.GetFiles(dir);
    byte[] result = null;
    using (var stream = new MemoryStream())
    {
        using (var archive = new ZipArchive(stream, ZipArchiveMode.Create))
        {
            foreach (var file in files)
                archive.CreateEntryFromFile(file, Path.GetFileName(file), CompressionLevel.Optimal);

            stream.Position = 0;
            result = new byte[stream.Length];
            stream.Read(result, 0, (int)stream.Length);
        }
    }

    return result;
}

我比较了第一个和第二个方法的数组,发现它们是相等的,只是第一个数组的末尾有一个rest字节,这使得zip存档可以打开。如何用压缩内存方法解决此问题?我试图避免将数据存储在磁盘上。

在读取压缩包之前,必须先关闭压缩包:

using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true))
{
    foreach (var file in files)
        archive.CreateEntryFromFile(file, Path.GetFileName(file), CompressionLevel.Optimal);
}

stream.Position = 0;
result = new byte[stream.Length];
stream.Read(result, 0, (int)stream.Length);        

// Note that you can replace the previous 3 rows
// from stream.Position = 0 onward) with:
//result = stream.ToArray();
但是,必须将ZipArchive设置为在流关闭时不释放流,最后设置为true

通过这种方式,拉链被冲到流中。如果您注意到,您在FileStream示例中做得正确

通常,您应该在执行stream.Position=0之前执行stream.Flush,因为流可能有一些未写入的内部缓冲区,但对于MemoryStream,这是不必要的,因为

重写Stream.Flush方法,以便不执行任何操作


阅读前必须先关闭拉链:

using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true))
{
    foreach (var file in files)
        archive.CreateEntryFromFile(file, Path.GetFileName(file), CompressionLevel.Optimal);
}

stream.Position = 0;
result = new byte[stream.Length];
stream.Read(result, 0, (int)stream.Length);        

// Note that you can replace the previous 3 rows
// from stream.Position = 0 onward) with:
//result = stream.ToArray();
但是,必须将ZipArchive设置为在流关闭时不释放流,最后设置为true

通过这种方式,拉链被冲到流中。如果您注意到,您在FileStream示例中做得正确

通常,您应该在执行stream.Position=0之前执行stream.Flush,因为流可能有一些未写入的内部缓冲区,但对于MemoryStream,这是不必要的,因为

重写Stream.Flush方法,以便不执行任何操作


我试过这个密码。但它抛出了一个ObjectDisposedException。添加stream.Flush无效。@kvantt已测试。添加一个true作为新ZipArchive的最后一个参数。请参阅添加的解释。我尝试了此代码。但它抛出了一个ObjectDisposedException。添加stream.Flush无效。@kvantt已测试。添加一个true作为新ZipArchive的最后一个参数。见添加的解释。