2011-01-19 13 views
5

ZipOutputStreamは、フォルダ内のファイルのみを圧縮します。サブフォルダも圧縮したいどうすればこれを達成できますか?ZipOutputStreamを使用したZipサブフォルダ

+2

を使用して

少なくとも、どの回答が有用かを示しています。あなたの200以上の質問のうち、約120点の回答が必要な場合は(回答が満足できるものであれば)、それぞれの回答はあなたに2点の追加ポイントを与え、将来のあなたの質問の視聴者を助けます。 。あなたが得ることができる120 * 2rep = 240の代理人。 – slugster

答えて

7

ジップ内のすべてのファイルを追加するには、ディレクトリを再帰的に探索する必要があります。あなたが望むなら

はこの小さなヘルパーを参照してください:

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

これはサブフォルダを圧縮せず、zipアーカイブにフォルダを追加したいと思います。 – BreakHead

+0

このコードを試しましたか?それはサブフォルダをきちんと圧縮します(DirExploreメソッドを参照してください) – Vinzz

+1

空のディレクトリは圧縮しませんのでご注意ください。 – Vinzz

2

C#MVPピーターBrombergによるこの記事では、あなたの問題を解決することがあります。Zip/Unzip folders and files with C#。完全なコードとサンプルプロジェクトがあります。

0

代替(ともっと便利な)私はちょうどつまずいたソリューション:私はあなたがこの質問を放棄していないとの回答をマークするために戻ってことを願っていますSevenZipSharpプロジェクト

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

私のために働いてくれてありがとう – mrbm

+0

仕上げ()とクローズ()の仕方は、Disposeパターンではありません。 :( –

関連する問題