我试图使用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存档?


当前回答

以防万一,如果有人想通过SaveFileDialog保存一个动态zip文件。

        var logFileName = "zip_filename.zip";
        appLogSaver.FileName = logFileName;
        appLogSaver.Filter = "LogFiles|*.zip";
        appLogSaver.DefaultExt = "zip";
        DialogResult resDialog = appLogSaver.ShowDialog();

        if (resDialog.ToString() == "OK")
        {
            System.IO.FileStream fs = (System.IO.FileStream)appLogSaver.OpenFile();

            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))
                        {
                            //read your existing file and put the content here 
                            streamWriter.Write("Bar!");
                        }
                    }

                    var demoFile2 = archive.CreateEntry("foo2.txt");
                    using (var entryStream = demoFile2.Open())
                    {
                        using (var streamWriter = new StreamWriter(entryStream))
                        {
                            streamWriter.Write("Bar2!");
                        }
                    }
                }

                memoryStream.Seek(0, SeekOrigin.Begin);
                memoryStream.CopyTo(fs);
            }
            fs.Close();
        }

其他回答

在将流复制到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);
}

`

只是另一个版本的压缩不写任何文件。

string fileName = "export_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".xlsx";
byte[] fileBytes = here is your file in bytes
byte[] compressedBytes;
string fileNameZip = "Export_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".zip";

using (var outStream = new MemoryStream())
{
    using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
    {
        var fileInArchive = archive.CreateEntry(fileName, CompressionLevel.Optimal);
        using (var entryStream = fileInArchive.Open())
        using (var fileToCompressStream = new MemoryStream(fileBytes))
        {
            fileToCompressStream.CopyTo(entryStream);
        }
    }
    compressedBytes = outStream.ToArray();
}

感谢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 (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 );
            }
        }