Iva*_*kin 1 .net compression zip
我正在使用 .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;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我试图用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;
}
Run Code Online (Sandbox Code Playgroud)
我比较了第一种和第二种方法中的数组,发现它们是相等的,只是第一个数组在末尾有一个剩余字节,这使得 zip 存档可以打开。如何在CompressInMemory方法中解决此问题?我试图避免将数据存储在磁盘上。
在阅读之前,您必须“关闭”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();
Run Code Online (Sandbox Code Playgroud)
但是您必须将 设置ZipArchive为在流true关闭时使其保持“未处置”(最终)。
通过这种方式,zip 被“刷新”到流中。如果你注意到你在FileStream例子中做对了。
一般来说,你应该stream.Flush() 在做之前stream.Position = 0,因为它stream可能有一些未写的内部缓冲区,但这MemoryStream不是必需的,因为MemoryStream.Flush()
覆盖 Stream.Flush 方法,以便不执行任何操作。