我试图使用MemoryStream创建一个简单的演示文本文件的ZIP存档,如下所示:

using (var memoryStream = new MemoryStream())
using (var archive = new ZipArchive(memoryStream , ZipArchiveMode.Create))
{
    var demoFile = archive.CreateEntry("foo.txt");

    using (var entryStream = demoFile.Open())
    using (var streamWriter = new StreamWriter(entryStream))
    {
        streamWriter.Write("Bar!");
    }

    using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
    {
        stream.CopyTo(fileStream);
    }
}

如果我运行这段代码,就会创建归档文件本身,但foo.txt不会。

然而,如果我直接用文件流替换MemoryStream,存档将被正确创建:

using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
using (var archive = new ZipArchive(fileStream, FileMode.Create))
{
    // ...
}

是否可以使用MemoryStream来创建没有FileStream的ZIP存档?


当前回答

在将流复制到zip流之前,将其位置设置为0。

using (var memoryStream = new MemoryStream())
{
 using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
 {
  var demoFile = archive.CreateEntry("foo.txt");

  using (var entryStream = demoFile.Open())
  using (var streamWriter = new StreamWriter(entryStream))
  {
     streamWriter.Write("Bar!");
  }
 }

 using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
   {
     memoryStream.Position=0;
     memoryStream.WriteTo(fileStream);
   }
 }

其他回答

函数返回包含zip文件的流

public static Stream ZipGenerator(List<string> files)
    {
        ZipArchiveEntry fileInArchive;
        Stream entryStream;
        int i = 0;
        List<byte[]> byteArray = new List<byte[]>();

        foreach (var file in files)
        {
            byteArray.Add(File.ReadAllBytes(file));
        }

        var outStream = new MemoryStream();

        using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
        {
            foreach (var file in files)
            {
                fileInArchive=(archive.CreateEntry(Path.GetFileName(file), CompressionLevel.Optimal));

                using (entryStream = fileInArchive.Open())
                {
                        using (var fileToCompressStream = new MemoryStream(byteArray[i]))
                        {
                            fileToCompressStream.CopyTo(entryStream);
                        }
                        i++;
                }
            }
        }
        outStream.Position = 0;
        return outStream;
    }

如果你想,写zip文件流。

using (var fileStream = new FileStream(@"D:\Tools\DBExtractor\DBExtractor\bin\Debug\test.zip", FileMode.Create))
{
   outStream.Position = 0;
   outStream.WriteTo(fileStream);
}

`

您需要完成写入内存流,然后读取缓冲区。

        using (var memoryStream = new MemoryStream())
        {
            using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create))
            {
                var demoFile = archive.CreateEntry("foo.txt");

                using (var entryStream = demoFile.Open())
                using (var streamWriter = new StreamWriter(entryStream))
                {
                    streamWriter.Write("Bar!");
                }
            }

            using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
            {
                var bytes = memoryStream.GetBuffer();
                fileStream.Write(bytes,0,bytes.Length );
            }
        }

感谢ZipArchive创建无效的ZIP文件,我得到:

using (var memoryStream = new MemoryStream())
{
   using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
   {
      var demoFile = archive.CreateEntry("foo.txt");

      using (var entryStream = demoFile.Open())
      using (var streamWriter = new StreamWriter(entryStream))
      {
         streamWriter.Write("Bar!");
      }
   }

   using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
   {
      memoryStream.Seek(0, SeekOrigin.Begin);
      memoryStream.CopyTo(fileStream);
   }
}

这表明我们需要在使用ZipArchive之前调用Dispose,正如Amir所建议的,这可能是因为它将最后的字节(如校验和)写入存档,使其完整。但是为了不关闭流,这样我们就可以重用它,你需要将true作为第三个参数传递给ZipArchive。

using System;
using System.IO;
using System.IO.Compression;

namespace ConsoleApplication
{
    class Program`enter code here`
    {
        static void Main(string[] args)
        {
            using (FileStream zipToOpen = new FileStream(@"c:\users\exampleuser\release.zip", FileMode.Open))
            {
                using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
                {
                    ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt");
                    using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                    {
                            writer.WriteLine("Information about this package.");
                            writer.WriteLine("========================");
                    }
                }
            }
        }
    }
}

对我来说,这样做是可以的:

using (var memoryStream = new MemoryStream())
{
   using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
   {
      var file = archive.CreateEntry("file.json");
      using var entryStream = file.Open();
      using var streamWriter = new StreamWriter(entryStream);
      streamWriter.WriteLine(someJsonLine);
   }
}