ZipArchive 无法使用 MemoryStream 正确压缩文件
ZipArchive does not properly compress files with MemoryStream
我正在使用 .NET 4.5 中的 ZipArchive,它可以与 FileStream
:
一起正常工作
public static byte[] CompressWithFiles(string dir)
{
var archiveName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".zip");
var files = Directory.GetFiles(testsConsoleDir);
using (var stream = new FileStream(archiveName, FileMode.Create))
{
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create))
{
foreach (var file in files)
archive.CreateEntryFromFile(file, Path.GetFileName(file), CompressionLevel.Optimal);
}
}
byte[] result = File.ReadAllBytes(archiveName);
return result;
}
但是如果我试图用 MemoryStream
压缩文件,它 returns 无法打开的字节数组被保存到磁盘:
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;
}
我比较了第一种和第二种方法的数组,发现它们是相等的,除了第一个数组末尾有一个剩余字节,这使得 zip 存档可以打开。如何在 CompressInMemory
方法中解决此问题?我试图避免数据存储在磁盘上。
您必须"close" 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
以在关闭时离开流 "non-disposed"(最后的 true
)。
通过这种方式,zip "flushed" 到流中。如果您注意到您在 FileStream
示例中做对了。
通常你应该stream.Flush()
在做stream.Position = 0
之前,因为stream
可能有一些未写的内部缓冲区,但是MemoryStream
这不是必需的,因为 MemoryStream.Flush()
Overrides the Stream.Flush method so that no action is performed.
我正在使用 .NET 4.5 中的 ZipArchive,它可以与 FileStream
:
public static byte[] CompressWithFiles(string dir)
{
var archiveName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".zip");
var files = Directory.GetFiles(testsConsoleDir);
using (var stream = new FileStream(archiveName, FileMode.Create))
{
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create))
{
foreach (var file in files)
archive.CreateEntryFromFile(file, Path.GetFileName(file), CompressionLevel.Optimal);
}
}
byte[] result = File.ReadAllBytes(archiveName);
return result;
}
但是如果我试图用 MemoryStream
压缩文件,它 returns 无法打开的字节数组被保存到磁盘:
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;
}
我比较了第一种和第二种方法的数组,发现它们是相等的,除了第一个数组末尾有一个剩余字节,这使得 zip 存档可以打开。如何在 CompressInMemory
方法中解决此问题?我试图避免数据存储在磁盘上。
您必须"close" 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
以在关闭时离开流 "non-disposed"(最后的 true
)。
通过这种方式,zip "flushed" 到流中。如果您注意到您在 FileStream
示例中做对了。
通常你应该stream.Flush()
在做stream.Position = 0
之前,因为stream
可能有一些未写的内部缓冲区,但是MemoryStream
这不是必需的,因为 MemoryStream.Flush()
Overrides the Stream.Flush method so that no action is performed.