2013-06-21 11 views
92

Próbuję utworzyć archiwum ZIP z prostego pliku tekstowego demo przy użyciu innego MemoryStream następująco:Tworzenie archiwum ZIP w pamięci Korzystanie System.IO.Compression

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

Jeśli uruchomić ten kod, sam plik archiwum został utworzony, ale nie jest to foo.txt.

Jednakże, jeśli mogę wymienić MemoryStream bezpośrednio ze strumienia pliku, archiwum jest tworzony poprawnie:

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

Czy jest możliwe aby użyć MemoryStream stworzyć archiwum ZIP bez FileStream?

+0

to może być coś zrobić z Zużyty? w [przykład] (http://msdn.microsoft.com/en-us/library/hh158346.aspx) nie używają 'using' dla' entry.Open', tylko zgadywania. – Sinatr

+0

@Sinatr: W takim przypadku powinienem dostać ObjectDisposedException lub przynajmniej pusty plik, czy nie powinienem? –

+0

Pozycja twoich plików przechodzi do końca pliku, więc nie można nic napisać, więc jeśli spróbujesz zresetować właściwość pozycji strumienia do 0, to zadziała. –

Odpowiedz

167

Dzięki https://stackoverflow.com/a/12350106/222748 mam:

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

Więc musimy wywołać wyrzucać na ZipArchive zanim możemy go używać, co oznacza, przechodząc „true” jako trzeci parametr do ZipArchive, więc możemy nadal dostęp do strumienia po jego wyrzuceniu.

+11

Wygląda na to, że ZipArchive sumuje sumę kontrolną i finalizuje archiwum, kiedy się go wyrzuca, a jeśli użyje strumienia przed pozbyciem się, archiwum zostanie uszkodzone. – Amir

+0

@Amir, czy możesz to wyjaśnić? –

+0

@JoshStodola ZipArchive dodaj sumę kontrolną na końcu archiwum, aby określić uszkodzenie lub zmianę (powody bezpieczeństwa). Tak więc do czasu zamknięcia archiwum lub usunięcia go, suma kontrolna nie jest uwzględniona w strumieniu. Mam nadzieję, że wyjaśnię to jasno! – Amir

4

Musisz zakończyć zapisywanie strumienia pamięci, a następnie odczytać bufor.

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

Ustaw pozycję strumienia na 0 przed skopiowaniem do strumienia 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); 
    } 
} 
-2
 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(); 
    } 
22

Kolejna wersja skompresowanie bez pisania jakiegokolwiek pliku.

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(); 
     } 
+0

Dzięki! Właśnie dodałem linię kodu do konwersji bajtów do pliku zip – Elnoor

1

To jest droga do przekształcenia podmiotu do pliku XML, a następnie skompresować go:

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

}

1
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("========================"); 
        } 
       } 
      } 
     } 
    } 
} 
Powiązane problemy