Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
492 views
in Technique[技术] by (71.8m points)

c# - ZipArchive creates invalid ZIP file

I am trying to create a new ZIP package from code with one entry and save the ZIP package to a file. I am trying to achive this with the System.IO.Compression.ZipArchive class. I am creating the ZIP package with the following code:

using (MemoryStream zipStream = new MemoryStream())
{
    using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create))
    {
        var entry = zip.CreateEntry("test.txt");
        using (StreamWriter sw = new StreamWriter(entry.Open()))
        {
            sw.WriteLine(
                "Etiam eros nunc, hendrerit nec malesuada vitae, pretium at ligula.");
        }

Then I save the ZIP to a file either in WinRT:

        var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("test.zip", CreationCollisionOption.ReplaceExisting);
        zipStream.Position = 0;
        using (Stream s = await file.OpenStreamForWriteAsync())
        {
            zipStream.CopyTo(s);
        }

Or in normal .NET 4.5:

        using (FileStream fs = new FileStream(@"C:Tempest.zip", FileMode.Create))
        {
            zipStream.Position = 0;
            zipStream.CopyTo(fs);
        }

However, I can't open the produced files neither in Windows Explorer, WinRAR, etc. (I checked that the size of the produced file matches the Length of the zipStream, so the stream itself was saved to the file correctly.)
Am I doing something wrong or is there a problem with the ZipArchive class?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I found the—in hindsight, obvious—error in my code. The ZipArchive has to be disposed to make it write its content to its underlying stream. So I had to save the stream to a file after the end of the using block of the ZipArchive.
And it was important to set the leaveOpen argument of its constructor to true, to make it not close the underlying stream. So here is the complete working solution:

using (MemoryStream zipStream = new MemoryStream())
{
    using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
    {
        var entry = zip.CreateEntry("test.txt");
        using (StreamWriter sw = new StreamWriter(entry.Open()))
        {
            sw.WriteLine(
                "Etiam eros nunc, hendrerit nec malesuada vitae, pretium at ligula.");
        }
    }

    var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(
        "test.zip",
        CreationCollisionOption.ReplaceExisting);

    zipStream.Position = 0;
    using (Stream s = await file.OpenStreamForWriteAsync())
    {
        zipStream.CopyTo(s);
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...