2011-01-19 9 views
5

ZipOutputStream solo zip i file in una cartella. Voglio anche comprimere le sottocartelle. Come posso raggiungere questo obiettivo?Sottocartelle Zip con ZipOutputStream

+2

Spero che non avete abbandonato questa domanda e sarà di nuovo a segnare una risposta o almeno indicare quale risposta è stata utile. Delle oltre 200 domande avrai circa 120 che hanno bisogno di una risposta contrassegnata (se è stata fornita una risposta soddisfacente), ciascuna risposta contrassegnata ti farà guadagnare altri 2 punti rep e aiuterà i futuri spettatori della tua domanda a sapere quale sia stata la risposta migliore . 120 * 2rips = 240 rep che potresti ottenere. – slugster

risposta

7

È necessario esplorare in modo ricorsivo la directory per aggiungere tutti i file nello zip.

Vedi questo piccolo aiuto, se lo si desidera:

using ICSharpCode.SharpZipLib.Zip; 
    using ICSharpCode.SharpZipLib.Checksums; 
    using System.IO; 
    using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Collections; 
    using System.Text.RegularExpressions; 

    namespace Zip 
{ 
    /// <summary> 
    /// Uses Sharpziplib so as to create a non flat zip archive 
    /// </summary> 
    public abstract class ZipManager 
    { 
     /// <summary> 
     /// will zip directory .\toto as .\toto.zip 
     /// </summary> 
     /// <param name="stDirToZip"></param> 
     /// <returns></returns> 
     public static string CreateZip(string stDirToZip) 
     { 
      try 
      { 
       DirectoryInfo di = new DirectoryInfo(stDirToZip); 
       string stZipPath = di.Parent.FullName + "\\" + di.Name + ".zip"; 

       CreateZip(stZipPath, stDirToZip); 

       return stZipPath; 
      } 
      catch (Exception) 
      { 
       throw; 
      } 
     } 

     /// <summary> 
     /// Main method 
     /// </summary> 
     /// <param name="stZipPath">path of the archive wanted</param> 
     /// <param name="stDirToZip">path of the directory we want to create, without ending backslash</param> 
     public static void CreateZip(string stZipPath, string stDirToZip) 
     { 
      try 
      { 
       //Sanitize inputs 
       stDirToZip = Path.GetFullPath(stDirToZip); 
       stZipPath = Path.GetFullPath(stZipPath); 

       Console.WriteLine("Zip directory " + stDirToZip); 

       //Recursively parse the directory to zip 
       Stack<FileInfo> stackFiles = DirExplore(stDirToZip); 

       ZipOutputStream zipOutput = null; 

       if (File.Exists(stZipPath)) 
        File.Delete(stZipPath); 

       Crc32 crc = new Crc32(); 
       zipOutput = new ZipOutputStream(File.Create(stZipPath)); 
       zipOutput.SetLevel(6); // 0 - store only to 9 - means best compression 

       Console.WriteLine(stackFiles.Count + " files to zip.\n"); 

       int index = 0; 
       foreach (FileInfo fi in stackFiles) 
       { 
        ++index; 
        int percent = (int)((float)index/((float)stackFiles.Count/100)); 
        if (percent % 1 == 0) 
        { 
         Console.CursorLeft = 0; 
         Console.Write(_stSchon[index % _stSchon.Length].ToString() + " " + percent + "% done."); 
        } 
        FileStream fs = File.OpenRead(fi.FullName); 

        byte[] buffer = new byte[fs.Length]; 
        fs.Read(buffer, 0, buffer.Length); 

        //Create the right arborescence within the archive 
        string stFileName = fi.FullName.Remove(0, stDirToZip.Length + 1); 
        ZipEntry entry = new ZipEntry(stFileName); 

        entry.DateTime = DateTime.Now; 

        // set Size and the crc, because the information 
        // about the size and crc should be stored in the header 
        // if it is not set it is automatically written in the footer. 
        // (in this case size == crc == -1 in the header) 
        // Some ZIP programs have problems with zip files that don't store 
        // the size and crc in the header. 
        entry.Size = fs.Length; 
        fs.Close(); 

        crc.Reset(); 
        crc.Update(buffer); 

        entry.Crc = crc.Value; 

        zipOutput.PutNextEntry(entry); 

        zipOutput.Write(buffer, 0, buffer.Length); 
       } 
       zipOutput.Finish(); 
       zipOutput.Close(); 
       zipOutput = null; 
      } 
      catch (Exception) 
      { 
       throw; 
      } 
     } 


     static private Stack<FileInfo> DirExplore(string stSrcDirPath) 
     { 
      try 
      { 
       Stack<DirectoryInfo> stackDirs = new Stack<DirectoryInfo>(); 
       Stack<FileInfo> stackPaths = new Stack<FileInfo>(); 

       DirectoryInfo dd = new DirectoryInfo(Path.GetFullPath(stSrcDirPath)); 

       stackDirs.Push(dd); 
       while (stackDirs.Count > 0) 
       { 
        DirectoryInfo currentDir = (DirectoryInfo)stackDirs.Pop(); 

        try 
        { 
         //Process .\files 
         foreach (FileInfo fileInfo in currentDir.GetFiles()) 
         { 
          stackPaths.Push(fileInfo); 
         } 

         //Process Subdirectories 
         foreach (DirectoryInfo diNext in currentDir.GetDirectories()) 
          stackDirs.Push(diNext); 
        } 
        catch (Exception) 
        {//Might be a system directory 
        } 
       } 
       return stackPaths; 
      } 
      catch (Exception) 
      { 
       throw; 
      } 
     } 

     private static char[] _stSchon = new char[] { '-', '\\', '|', '/' }; 
    } 
} 
+0

Questo non zipperà le sottocartelle, voglio aggiungere la cartella nell'archivio zip. – BreakHead

+0

Hai provato questo codice? Blocca le sottocartelle abbastanza bene (vedere il metodo DirExplore) – Vinzz

+1

Si noti che tuttavia non chiuderà le directory vuote. – Vinzz

0

alternativa (e più a portata di mano) soluzione che ho appena imbattuto:

utilizzando il SevenZipSharp progetto

var compressor = new SevenZipCompressor(); 
compressor.ArchiveFormat = OutArchiveFormat.SevenZip; 
compressor.CompressionLevel = CompressionLevel.High; 
compressor.CompressionMode = CompressionMode.Create; 
compressor.PreserveDirectoryRoot = false; 
compressor.FastCompression = true; 
compressor.CompressDirectory(dir.FullName, zipFile.FullName); 
3
public static void ZipDirectoryKeepRelativeSubfolder(string zipFilePath, string directoryToZip) 
{ 
    var filenames = Directory.GetFiles(directoryToZip, "*.*", SearchOption.AllDirectories); 
    using (var s = new ZipOutputStream(File.Create(zipFilePath))) 
    { 
     s.SetLevel(9);// 0 - store only to 9 - means best compression 

     var buffer = new byte[4096]; 

     foreach (var file in filenames) 
     { 
      var relativePath = file.Substring(directoryToZip.Length).TrimStart('\\'); 
      var entry = new ZipEntry(relativePath); 
      entry.DateTime = DateTime.Now; 
      s.PutNextEntry(entry); 

      using (var fs = File.OpenRead(file)) 
      { 
       int sourceBytes; 
       do 
       { 
        sourceBytes = fs.Read(buffer, 0, buffer.Length); 
        s.Write(buffer, 0, sourceBytes); 
       } while (sourceBytes > 0); 
      } 
     } 
     s.Finish(); 
     s.Close(); 
    } 
} 
+0

ha funzionato per me, grazie – mrbm

+0

il modo con finish() e close() funziona, non con il modello Dispose. :( –