使用 System.IO.Compression 在内存中创建 ZIP 存档

Posted

技术标签:

【中文标题】使用 System.IO.Compression 在内存中创建 ZIP 存档【英文标题】:Creating a ZIP archive in memory using System.IO.Compression 【发布时间】:2013-06-18 10:01:59 【问题描述】:

我正在尝试使用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 存档?

【问题讨论】:

仅供参考:.ZipArchive 至少需要 .NET 4.5。参见 Rick Strahl 的 .NET 4.5 is an in-place replacement for .NET 4.0 ~~ 也参见 I didn't find “ZipFile” class in the “System.IO.Compression” namespace 如果您想要一个使用二进制数据而不是字符串的示例,这里有一个很好的解决方案:***.com/questions/48927574/… 【参考方案1】:

我迟到了,但在某些情况下,您无法访问 ZipArchive 的构造函数来设置 leaveOpen 参数,并且您不希望将 ZIP 写入磁盘。就我而言,我在内部使用的 AsiceArchive 类创建了一个 ZipArchive,但没有将 leaveOpen 设置为 true。

我创建了Stream 的一个子类,它将所有调用委托给一个内部流(使用 ReSharper 单击几下)。这个类不是一次性的,所以当ZipArchive 被释放时,内部流不会发生任何事情。

public class NondisposingStreamWrapper : Stream

    private readonly Stream _streamImplementation;

    public NondisposingStreamWrapper(Stream inner) => _streamImplementation = inner;

    public override void Flush() => _streamImplementation.Flush();

    public override int Read(byte[] buffer, int offset, int count) => _streamImplementation.Read(buffer, offset, count);

    public override long Seek(long offset, SeekOrigin origin) => _streamImplementation.Seek(offset, origin);

    public override void SetLength(long value) => _streamImplementation.SetLength(value);

    public override void Write(byte[] buffer, int offset, int count) => _streamImplementation.Write(buffer, offset, count);

    public override bool CanRead => _streamImplementation.CanRead;

    public override bool CanSeek => _streamImplementation.CanSeek;

    public override bool CanWrite => _streamImplementation.CanWrite;

    public override long Length => _streamImplementation.Length;

    public override long Position
    
        get => _streamImplementation.Position;
        set => _streamImplementation.Position = value;
    

像这样使用它:

using var memoryStream = new MemoryStream();
var output = new NondisposingStreamWrapper(memoryStream);

using (var archive = new ZipArchive(output, ZipArchiveMode.Create))

    // add entries to archive


memoryStream.Flush();
memoryStream.Position = 0;

// write to file just for testing purposes
File.WriteAllBytes("out.zip", memoryStream.ToArray());

【讨论】:

【参考方案2】:

感谢ZipArchive creates invalid ZIP file,我得到了:

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 之后重新使用它。

【讨论】:

【参考方案3】:

以防万一,如果有人想通过 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();
        

【讨论】:

【参考方案4】:

返回包含 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);

`

【讨论】:

先将所有文件读入内存是极大的内存浪费。您最终会在内存中两次获得所有文件。一次在byteArray 和一次在ZipArchive。更不用说您根本不需要将文件加载到内存中。使用流式传输,如所有其他现有答案所示。 @MartinPrikryl 问题是将 zip 文件写入内存的方法。这就是我使用内存的原因。当然最好的方法是写入本地 我知道问题是关于什么的。我的评论的重点是,您在内存中创建 ZIP 文件的实现非常低效。其他答案中的实现更好。【参考方案5】:

MVC 的工作解决方案

    public ActionResult Index()
    
        string fileName = "test.pdf";
        string fileName1 = "test.vsix";
        string fileNameZip = "Export_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".zip";

        byte[] fileBytes = System.IO.File.ReadAllBytes(@"C:\test\test.pdf");
        byte[] fileBytes1 = System.IO.File.ReadAllBytes(@"C:\test\test.vsix");
        byte[] compressedBytes;
        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);
                

                var fileInArchive1 = archive.CreateEntry(fileName1, CompressionLevel.Optimal);
                using (var entryStream = fileInArchive1.Open())
                using (var fileToCompressStream = new MemoryStream(fileBytes1))
                
                    fileToCompressStream.CopyTo(entryStream);
                


            
            compressedBytes = outStream.ToArray();
        
        return File(compressedBytes, "application/zip", fileNameZip);
    

【讨论】:

Controller.File method has an overload that accepts Stream。使用它来避免在内存中创建另一个 ZIP 文件副本。 天哪,这是谷歌搜索一个小时后的第一个直接答案。谢谢! 这个解决方案完美!谢谢!您甚至不需要移动字节数组 (byte[])。只需使用 MemoryStream 并且不要忘记在返回结果之前寻找零 (.Seek(0, SeekOrigin.Begin);) 可以在 donet core 5.* w/WebApi 中确认这对我有用。【参考方案6】:

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

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();

【讨论】:

【参考方案7】:
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("========================");
                    
                
            
        
    

【讨论】:

【参考方案8】:

这是将实体转换为 XML 文件然后对其进行压缩的方法:

private  void downloadFile(EntityXML xml) 

string nameDownloadXml = "File_1.xml";
string nameDownloadZip = "File_1.zip";

var serializer = new XmlSerializer(typeof(EntityXML));

Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.AddHeader("content-disposition", "attachment;filename=" + nameDownloadZip);

using (var memoryStream = new MemoryStream())

    using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
    
        var demoFile = archive.CreateEntry(nameDownloadXml);
        using (var entryStream = demoFile.Open())
        using (StreamWriter writer = new StreamWriter(entryStream, System.Text.Encoding.UTF8))
        
            serializer.Serialize(writer, xml);
        
    

    using (var fileStream = Response.OutputStream)
    
        memoryStream.Seek(0, SeekOrigin.Begin);
        memoryStream.CopyTo(fileStream);
    


Response.End();

【讨论】:

【参考方案9】:
       private void button6_Click(object sender, EventArgs e)
    

        //create With Input FileNames
        AddFileToArchive_InputByte(new ZipItem[] new ZipItem( @"E:\b\1.jpg",@"images\1.jpg"),
            new ZipItem(@"E:\b\2.txt",@"text\2.txt"), @"C:\test.zip");

        //create with input stream
        AddFileToArchive_InputByte(new ZipItem[] new ZipItem(File.ReadAllBytes( @"E:\b\1.jpg"),@"images\1.jpg"),
            new ZipItem(File.ReadAllBytes(@"E:\b\2.txt"),@"text\2.txt"), @"C:\test.zip");

        //Create Archive And Return StreamZipFile
        MemoryStream GetStreamZipFile = AddFileToArchive(new ZipItem[] new ZipItem( @"E:\b\1.jpg",@"images\1.jpg"),
            new ZipItem(@"E:\b\2.txt",@"text\2.txt"));


        //Extract in memory
        ZipItem[] ListitemsWithBytes = ExtractItems(@"C:\test.zip");

        //Choese Files For Extract To memory
        List<string> ListFileNameForExtract = new List<string>(new string[]  @"images\1.jpg", @"text\2.txt" );
        ListitemsWithBytes = ExtractItems(@"C:\test.zip", ListFileNameForExtract);


        // Choese Files For Extract To Directory
        ExtractItems(@"C:\test.zip", ListFileNameForExtract, "c:\\extractFiles");

    

    public struct ZipItem
    
        string _FileNameSource;
        string _PathinArchive;
        byte[] _Bytes;
        public ZipItem(string __FileNameSource, string __PathinArchive)
        
            _Bytes=null ;
            _FileNameSource = __FileNameSource;
            _PathinArchive = __PathinArchive;
        
        public ZipItem(byte[] __Bytes, string __PathinArchive)
        
            _Bytes = __Bytes;
            _FileNameSource = "";
            _PathinArchive = __PathinArchive;

        
        public string FileNameSource
        
            set
            
                FileNameSource = value;
            
            get
            
                return _FileNameSource;
            
        
        public string PathinArchive
        
            set
            
                _PathinArchive = value;
            
            get
            
                return _PathinArchive;
            
        
        public byte[] Bytes
        
            set
            
                _Bytes = value;
            
            get
            
                return _Bytes;
            
        
    


     public void AddFileToArchive(ZipItem[] ZipItems, string SeveToFile)
    

        MemoryStream memoryStream = new MemoryStream();

        //Create Empty Archive
        ZipArchive archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);

        foreach (ZipItem item in ZipItems)
        

            //Create Path File in Archive
            ZipArchiveEntry FileInArchive = archive.CreateEntry(item.PathinArchive);


            //Open File in Archive For Write
            var OpenFileInArchive = FileInArchive.Open();

            //Read Stream
            FileStream fsReader = new FileStream(item.FileNameSource, FileMode.Open, FileAccess.Read);

            byte[] ReadAllbytes = new byte[4096];//Capcity buffer
            int ReadByte = 0;
            while (fsReader.Position != fsReader.Length)
            
                //Read Bytes
                ReadByte = fsReader.Read(ReadAllbytes, 0, ReadAllbytes.Length);

                //Write Bytes
                OpenFileInArchive.Write(ReadAllbytes, 0, ReadByte);
            
            fsReader.Dispose();
            OpenFileInArchive.Close();


        
        archive.Dispose();

        using (var fileStream = new FileStream(SeveToFile, FileMode.Create))
        
            memoryStream.Seek(0, SeekOrigin.Begin);
            memoryStream.CopyTo(fileStream);
        





    
     public MemoryStream  AddFileToArchive(ZipItem[] ZipItems)
    

        MemoryStream memoryStream = new MemoryStream();

        //Create Empty Archive
        ZipArchive archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);

        foreach (ZipItem item in ZipItems)
        

            //Create Path File in Archive
            ZipArchiveEntry FileInArchive = archive.CreateEntry(item.PathinArchive);


            //Open File in Archive For Write
            var OpenFileInArchive = FileInArchive.Open();

            //Read Stream
            FileStream fsReader = new FileStream(item.FileNameSource, FileMode.Open, FileAccess.Read);

            byte[] ReadAllbytes = new byte[4096];//Capcity buffer
            int ReadByte = 0;
            while (fsReader.Position != fsReader.Length)
            
                //Read Bytes
                ReadByte = fsReader.Read(ReadAllbytes, 0, ReadAllbytes.Length);

                //Write Bytes
                OpenFileInArchive.Write(ReadAllbytes, 0, ReadByte);
            
            fsReader.Dispose();
            OpenFileInArchive.Close();


        
        archive.Dispose();




        return memoryStream;


    

     public void AddFileToArchive_InputByte(ZipItem[] ZipItems, string SeveToFile)
    

        MemoryStream memoryStream = new MemoryStream();

        //Create Empty Archive
        ZipArchive archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);

        foreach (ZipItem item in ZipItems)
        

            //Create Path File in Archive
            ZipArchiveEntry FileInArchive = archive.CreateEntry(item.PathinArchive);


            //Open File in Archive For Write
            var OpenFileInArchive = FileInArchive.Open();

            //Read Stream
          //  FileStream fsReader = new FileStream(item.FileNameSource, FileMode.Open, FileAccess.Read);

            byte[] ReadAllbytes = new byte[4096];//Capcity buffer
            int ReadByte = 4096 ;int  TotalWrite=0;
            while (TotalWrite != item.Bytes.Length)
            

                if(TotalWrite+4096>item.Bytes.Length)
                 ReadByte=item.Bytes.Length-TotalWrite;



                Array.Copy(item.Bytes, TotalWrite, ReadAllbytes, 0, ReadByte);




                //Write Bytes
                OpenFileInArchive.Write(ReadAllbytes, 0, ReadByte);
                TotalWrite += ReadByte;
            

            OpenFileInArchive.Close();


        
        archive.Dispose();

        using (var fileStream = new FileStream(SeveToFile, FileMode.Create))
        
            memoryStream.Seek(0, SeekOrigin.Begin);
            memoryStream.CopyTo(fileStream);
        


    
     public MemoryStream  AddFileToArchive_InputByte(ZipItem[] ZipItems)
    

        MemoryStream memoryStream = new MemoryStream();

        //Create Empty Archive
        ZipArchive archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);

        foreach (ZipItem item in ZipItems)
        

            //Create Path File in Archive
            ZipArchiveEntry FileInArchive = archive.CreateEntry(item.PathinArchive);


            //Open File in Archive For Write
            var OpenFileInArchive = FileInArchive.Open();

            //Read Stream
          //  FileStream fsReader = new FileStream(item.FileNameSource, FileMode.Open, FileAccess.Read);

            byte[] ReadAllbytes = new byte[4096];//Capcity buffer
            int ReadByte = 4096 ;int  TotalWrite=0;
            while (TotalWrite != item.Bytes.Length)
            

                if(TotalWrite+4096>item.Bytes.Length)
                 ReadByte=item.Bytes.Length-TotalWrite;



                Array.Copy(item.Bytes, TotalWrite, ReadAllbytes, 0, ReadByte);




                //Write Bytes
                OpenFileInArchive.Write(ReadAllbytes, 0, ReadByte);
                TotalWrite += ReadByte;
            

            OpenFileInArchive.Close();


        
        archive.Dispose();



        return memoryStream;
    

     public void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName)
     
         //Opens the zip file up to be read
         using (ZipArchive archive = ZipFile.OpenRead(sourceArchiveFileName))
         
             if (Directory.Exists(destinationDirectoryName)==false )
                 Directory.CreateDirectory(destinationDirectoryName);

             //Loops through each file in the zip file
             archive.ExtractToDirectory(destinationDirectoryName);

         
       
     public void   ExtractItems(string sourceArchiveFileName,List< string> _PathFilesinArchive, string destinationDirectoryName)
     

         //Opens the zip file up to be read
         using (ZipArchive archive = ZipFile.OpenRead(sourceArchiveFileName))
         


             //Loops through each file in the zip file
             foreach (ZipArchiveEntry file in archive.Entries)
             
                 int PosResult = _PathFilesinArchive.IndexOf(file.FullName);
                 if (PosResult != -1)
                 
                     //Create Folder
                     if (Directory.Exists( destinationDirectoryName + "\\" +Path.GetDirectoryName( _PathFilesinArchive[PosResult])) == false)
                         Directory.CreateDirectory(destinationDirectoryName + "\\" + Path.GetDirectoryName(_PathFilesinArchive[PosResult]));

                     Stream OpenFileGetBytes = file.Open();

                     FileStream   FileStreamOutput = new FileStream(destinationDirectoryName + "\\" + _PathFilesinArchive[PosResult], FileMode.Create);

                     byte[] ReadAllbytes = new byte[4096];//Capcity buffer
                     int ReadByte = 0; int TotalRead = 0; 
                     while (TotalRead != file.Length)
                     
                         //Read Bytes
                         ReadByte = OpenFileGetBytes.Read(ReadAllbytes, 0, ReadAllbytes.Length);
                         TotalRead += ReadByte;

                         //Write Bytes
                         FileStreamOutput.Write(ReadAllbytes, 0, ReadByte);
                     

                     FileStreamOutput.Close();
                     OpenFileGetBytes.Close();



                     _PathFilesinArchive.RemoveAt(PosResult);
                 

                 if (_PathFilesinArchive.Count == 0)
                     break;
             
         


     

     public ZipItem[] ExtractItems(string sourceArchiveFileName)
     
       List<  ZipItem> ZipItemsReading = new List<ZipItem>();
         //Opens the zip file up to be read
         using (ZipArchive archive = ZipFile.OpenRead(sourceArchiveFileName))
         


             //Loops through each file in the zip file
             foreach (ZipArchiveEntry file in archive.Entries)
             
                 Stream OpenFileGetBytes = file.Open();

                 MemoryStream memstreams = new MemoryStream();
                 byte[] ReadAllbytes = new byte[4096];//Capcity buffer
                 int ReadByte = 0; int TotalRead = 0;
                 while (TotalRead != file.Length)
                 
                     //Read Bytes
                     ReadByte = OpenFileGetBytes.Read(ReadAllbytes, 0, ReadAllbytes.Length);
                     TotalRead += ReadByte;

                     //Write Bytes
                     memstreams.Write(ReadAllbytes, 0, ReadByte);
                 

                 memstreams.Position = 0;
                 OpenFileGetBytes.Close();
                 memstreams.Dispose();

                 ZipItemsReading.Add(new ZipItem(memstreams.ToArray(),file.FullName));


             
         

         return ZipItemsReading.ToArray();
     
     public ZipItem[] ExtractItems(string sourceArchiveFileName,List< string> _PathFilesinArchive)
     
       List<  ZipItem> ZipItemsReading = new List<ZipItem>();
         //Opens the zip file up to be read
         using (ZipArchive archive = ZipFile.OpenRead(sourceArchiveFileName))
         

             //Loops through each file in the zip file
             foreach (ZipArchiveEntry file in archive.Entries)
             
                 int PosResult = _PathFilesinArchive.IndexOf(file.FullName); 
                 if (PosResult!= -1)
                 
                     Stream OpenFileGetBytes = file.Open();

                     MemoryStream memstreams = new MemoryStream();
                     byte[] ReadAllbytes = new byte[4096];//Capcity buffer
                     int ReadByte = 0; int TotalRead = 0;  
                     while (TotalRead != file.Length)
                     
                         //Read Bytes
                         ReadByte = OpenFileGetBytes.Read(ReadAllbytes, 0, ReadAllbytes.Length);
                         TotalRead += ReadByte;

                         //Write Bytes
                         memstreams.Write(ReadAllbytes, 0, ReadByte);
                     

                     //Create item
                     ZipItemsReading.Add(new ZipItem(memstreams.ToArray(),file.FullName));

                     OpenFileGetBytes.Close();
                     memstreams.Dispose();



                     _PathFilesinArchive.RemoveAt(PosResult);
                 

                 if (_PathFilesinArchive.Count == 0)
                     break;


             
         

         return ZipItemsReading.ToArray();
     

【讨论】:

【参考方案10】:

将流的位置设置为 0,然后再将其复制到 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.Position=0;
     memoryStream.WriteTo(fileStream);
   
 

【讨论】:

感谢您提供直接的解决方案。赞!!【参考方案11】:

你需要写完内存流然后读回缓冲区。

        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 );
            
        

【讨论】:

以上是关于使用 System.IO.Compression 在内存中创建 ZIP 存档的主要内容,如果未能解决你的问题,请参考以下文章

使用 vb.net 和 System.IO.Compression (.Net 4.5) 压缩文件

我没有在“System.IO.Compression”命名空间中找到“ZipFile”类

System.IO.Compression.ZipFile.CreateFromDirectory - 在 Mac 上打开时没有文件夹结构

使用 System.IO.Compression 压缩 Windows 10 Documents 文件夹,不包括重解析点

ZipFile (System.IO.Compression)、c# (WPF) 的字符提取问题

使用System.IO.Compression在内存中创建ZIP存档