使用通用流通过 SharpCompress 创建压缩文件
Posted
技术标签:
【中文标题】使用通用流通过 SharpCompress 创建压缩文件【英文标题】:Using a generic stream to create a zipped file with SharpCompress 【发布时间】:2017-06-01 10:44:45 【问题描述】:由于 System.IO.Compression seems to be out of reach for now 如果我想同时使用 dotnet core + net461,我已经尝试使用 SharpCompress
。
“读取 zip”部分很简单,但我很难找出如何写入 zip 流。
The wiki of the project 有点过时了。 This is the only example 我发现它适用于写入流。我试图遵循它并使其适应我的需求,但我被它抛出的异常困住了:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SharpCompress.Common;
using SharpCompress.Compressors.Deflate;
using SharpCompress.Writers;
using System;
using System.IO;
namespace DbManager.DjdbCore.Tests
[TestClass]
public class ZipTests
public ZipTests()
Directory.SetCurrentDirectory(AppContext.BaseDirectory);
[TestMethod]
public void Test()
var zip = File.OpenWrite(@"..\..\..\..\..\test-resources\zip_file_test.zip");
var writerOptions = new WriterOptions(CompressionType.Deflate);
var zipWriter = WriterFactory.Open(zip, ArchiveType.Zip, writerOptions);
var memoryStream = new MemoryStream();
var binaryWriter = new BinaryWriter(memoryStream);
binaryWriter.Write("Test string inside binary file - text to fill it up: qoiwjqefñlawijfñlaskdjfioqwjefñalskvndñaskvnqo`wiefowainvñaslkfjnwpowiqjfeopwiqjnfjñlaskdjfñlasdfjiowiqjefñaslkdjfñalskjfpqwoiefjqw");
var deflateStream = new DeflateStream(memoryStream, SharpCompress.Compressors.CompressionMode.Compress);
deflateStream.Write(memoryStream.ToArray(), 0, Convert.ToInt32(memoryStream.Length));
// EXCEPTION: SharpCompress.Compressors.Deflate.ZlibException: 'Cannot Read after Writing.'
// Source code: if (_streamMode != StreamMode.Reader) throw new ZlibException("Cannot Read after Writing.");
zipWriter.Write("test_file_inside_zip.bin", deflateStream, DateTime.Now);
zip.Flush();
zipWriter.Dispose();
zip.Dispose();
如果有帮助,这就是我使用库 System.IO.Compression
使用的(并且它有效,但仅在 dotnet 核心中):
private void WriteAsZipBinary()
//Open the zip file if it exists, else create a new one
var zip = ZipPackage.Open(this.FileFullPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
var zipStream = ZipManager.GetZipWriteStream(zip, nameOfFileInsideZip);
var memoryStream = new MemoryStream();
var binaryWriter = new BinaryWriter(memoryStream);
// Here is where strings etc are written to the binary file:
WriteStuffInBinaryStream(ref binaryWriter);
//Read all of the bytes from the file to add to the zip file
byte[] bites = new byte[Convert.ToInt32(memoryStream.Length - 1) + 1];
memoryStream.Position = 0;
memoryStream.Read(bites, 0, Convert.ToInt32(memoryStream.Length));
binaryWriter.Dispose();
binaryWriter = null;
memoryStream.Dispose();
memoryStream = null;
zipStream.Position = 0;
zipStream.Write(bites, 0, bites.Length);
zip.Close();
public static Stream GetZipWriteStream(Package zip, string renamedFileName)
//Replace spaces with an underscore (_)
string uriFileName = renamedFileName.Replace(" ", "_");
//A Uri always starts with a forward slash "/"
string zipUri = string.Concat("/", Path.GetFileName(uriFileName));
Uri partUri = new Uri(zipUri, UriKind.Relative);
string contentType = "Zip"; // System.Net.Mime.MediaTypeNames.Application.Zip;
//The PackagePart contains the information:
// Where to extract the file when it's extracted (partUri)
// The type of content stream (MIME type): (contentType)
// The type of compression: (CompressionOption.Normal)
PackagePart pkgPart = zip.CreatePart(partUri, contentType, CompressionOption.Normal);
//Compress and write the bytes to the zip file
return pkgPart.GetStream();
【问题讨论】:
【参考方案1】:我将在这里发布来自@adamhathcock(项目所有者)的answer on github:
[TestMethod]
public void Test()
var writerOptions = new WriterOptions(CompressionType.Deflate);
using(var zip = File.OpenWrite(@"..\..\..\..\..\test-resources\zip_file_test.zip"))
using(var zipWriter = WriterFactory.Open(zip, ArchiveType.Zip, writerOptions))
var memoryStream = new MemoryStream();
var binaryWriter = new BinaryWriter(memoryStream);
binaryWriter.Write("Test string inside binary file - text to fill it up: qoiwjqefñlawijfñlaskdjfioqwjefñalskvndñaskvnqo`wiefowainvñaslkfjnwpowiqjfeopwiqjnfjñlaskdjfñlasdfjiowiqjefñaslkdjfñalskjfpqwoiefjqw");
memoryStream.Position = 0;
zipWriter.Write("test_file_inside_zip.bin", memoryStream, DateTime.Now);
两件事:
写入后忘记重置 MemoryStream 以便读取。
您无需手动使用 DeflateStream。您已经告诉 ZipWriter 使用什么压缩。如果它有效,您将双重压缩实际上是垃圾的字节。
【讨论】:
以上是关于使用通用流通过 SharpCompress 创建压缩文件的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 sharpcompress 解压 .xz (lzma2) 文件
SharpCompress & LZMA2 7z 存档 - 特定文件的提取速度非常慢。为啥?备择方案?