使用通用流通过SharpCompress创建压缩文件

时间:2017-06-01 10:44:45

标签: c# .net-core sharpcompress

自System.IO.Compression seems to be out of reach for now以来,如果我想同时使用dotnet core + net461,我已尝试使用SharpCompress

"阅读拉链"部分很简单,但我无法找到如何写入压缩流。

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 个答案:

答案 0 :(得分: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);                          
    }
}

2件事:

  1. 写入后忘记重置MemoryStream,以便可以阅读。

  2. 您不需要手动使用DeflateStream。您已经告诉ZipWriter使用什么压缩。如果它有效,你可能会对字节进行双重压缩,这实际上就是垃圾。