2009-06-21 24 views
47

Có vẻ như không có Thư viện/API tích hợp trong C# để giải nén tệp zip. Tôi đang tìm một thư viện/API miễn phí (nguồn mở tốt hơn) có thể làm việc với .Net 3.5 + VSTS 2008 + C# để giải nén một tệp nén và trích xuất tất cả các tệp vào một thư mục cụ thể.đề xuất thư viện/API để giải nén tệp trong C#

Bất kỳ thư viện/API hoặc mẫu được đề xuất nào?

Trả lời

34

GPL

http://www.icsharpcode.net/OpenSource/SharpZipLib/

HOẶC ít hạn chế Ms-PL

http://www.codeplex.com/DotNetZip

Để hoàn thành này trả lời các khung lưới có ZipPackage tôi đã không mấy thành công với nó.

+1

. Net có tích hợp sẵn trong triển khai, nhưng không thể làm việc với –

+0

Tôi thích công việc đầu tiên. Đối với một. Net, bạn có nghĩa là lớp học nào? – George2

+0

Tại sao bạn có nghĩa là .Net ZipPackage là thành công ít hơn? – George2

2

Nếu bạn muốn sử dụng nén 7-zip, hãy kiểm tra Peter Bromberg của EggheadCafe article. Hãy coi chừng: các LZMA source code cho C# không có ý kiến ​​xml (thực sự, rất ít ý kiến ​​ở tất cả).

16

DotNetZip rất dễ sử dụng. Dưới đây là một mẫu unzip

using (var zip = Ionic.Zip.ZipFile.Read("archive.zip")) 
{ 
    zip.ExtractAll("unpack-directory"); 
} 

Nếu bạn có nhu cầu phức tạp hơn, như bạn muốn pick-and-chọn các mục để giải nén, hoặc nếu có mật khẩu, hoặc nếu bạn muốn kiểm soát các tên đường dẫn của các file trích xuất , hoặc vv vv, có rất nhiều tùy chọn. Check the help file để biết thêm ví dụ.

DotNetZip là nguồn mở và miễn phí.

9

Trước đây, tôi đã sử dụng DotNetZip (MS-PL), SharpZipLib (GPL) và 7ZIP SDK for C# (miền công cộng). Tất cả đều hoạt động tốt và là nguồn mở.

tôi sẽ chọn DotNetZip trong tình huống này, và đây là một số mẫu mã từ C# Examples page:

using (ZipFile zip = ZipFile.Read(ExistingZipFile)) 
{ 
    foreach (ZipEntry e in zip) 
    { 
    e.Extract(TargetDirectory); 
    } 
} 
+1

LGPL, chứ không phải GPL - sự khác biệt là khá lớn. –

+0

@Quandary cái nào? SharpZipLib là GPL, theo trang web của họ. –

+0

GPL với ngoại lệ đó (liên kết nó tĩnh hoặc động với dự án của bạn không bắt nguồn từ GPL) = LGPL (ok, quyền liên kết tĩnh không có trong LGPL, đó là lý do tại sao họ viết nó như thế này, nhưng liên kết tĩnh là không bình thường cho .NET). Thành thật mà nói, đó là một phiên bản tự do hơn của LGPL. –

23

Nếu tất cả những gì bạn muốn làm là giải nén nội dung của một tệp vào một thư mục và bạn biết bạn sẽ chỉ chạy trên Windows, bạn có thể sử dụng đối tượng Windows Shell. Tôi đã sử dụng dynamic từ Framework 4.0 trong ví dụ này, nhưng bạn có thể đạt được kết quả tương tự bằng cách sử dụng Type.InvokeMember.

dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application")); 

dynamic compressedFolderContents = shellApplication.NameSpace(sourceFile).Items; 
dynamic destinationFolder = shellApplication.NameSpace(destinationPath); 

destinationFolder.CopyHere(compressedFolderContents); 

Bạn có thể sử dụng FILEOP_FLAGS để kiểm soát hành vi của phương pháp CopyHere.

+1

Cho đến nay câu trả lời tuyệt vời nhất của câu trả lời tuyệt vời cho câu hỏi về tuổi già này! Điều này cần upvoting lớn. – Joshua

+1

Tôi phải đồng ý với @joshuam ... – dda

1

Nếu bạn không muốn sử dụng thành phần bên ngoài, dưới đây là một số mã tôi đã phát triển tối qua bằng lớp ZipPackage của .NET.

private static void Unzip() 
{ 
    var zipFilePath = "c:\\myfile.zip"; 
    var tempFolderPath = "c:\\unzipped"; 

    using (Package pkg = ZipPackage.Open(zipFilePath, FileMode.Open, FileAccess.Read)) 
    { 
     foreach (PackagePart part in pkg.GetParts()) 
     { 
      var target = Path.GetFullPath(Path.Combine(tempFolderPath, part.Uri.OriginalString.TrimStart('/'))); 
      var targetDir = target.Remove(target.LastIndexOf('\\')); 

      if (!Directory.Exists(targetDir)) 
       Directory.CreateDirectory(targetDir); 

      using (Stream source = part.GetStream(FileMode.Open, FileAccess.Read)) 
      { 
       CopyStream(source, File.OpenWrite(target)); 
      } 
     } 
    } 
} 

private static void CopyStream(Stream input, Stream output) 
{ 
    byte[] buffer = new byte[4096]; 
    int read; 
    while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
    { 
     output.Write(buffer, 0, read); 
    } 
} 

Những điều cần lưu ý:

  • Các kho lưu trữ ZIP PHẢI có một [Content_Types] .xml tập tin trong thư mục gốc của nó. Đây không phải là vấn đề đối với các yêu cầu của tôi vì tôi sẽ kiểm soát việc nén của bất kỳ tệp ZIP nào được trích xuất thông qua mã này. Để biết thêm thông tin về tệp .xml của [Content_Types], vui lòng tham khảo: http://msdn.microsoft.com/en-us/magazine/cc163372.aspx Có một tệp ví dụ bên dưới Hình 13 của bài viết.

  • Tôi chưa thử nghiệm phương pháp CopyStream để đảm bảo nó hoạt động chính xác, vì tôi đã phát triển phiên bản .NET 4.0 này bằng phương thức Stream.CopyTo().

1
#region CreateZipFile 
    public void StartZip(string directory, string zipfile_path) 
    { 
     Label1.Text = "Please wait, taking backup"; 
      #region Taking files from root Folder 
       string[] filenames = Directory.GetFiles(directory); 

       // path which the zip file built in 
       ZipOutputStream p = new ZipOutputStream(File.Create(zipfile_path)); 
       foreach (string filename in filenames) 
       { 
        FileStream fs = File.OpenRead(filename); 
        byte[] buffer = new byte[fs.Length]; 
        fs.Read(buffer, 0, buffer.Length); 
        ZipEntry entry = new ZipEntry(filename); 
        p.PutNextEntry(entry); 
        p.Write(buffer, 0 , buffer.Length); 
        fs.Close(); 
       } 
      #endregion 

      string dirName= string.Empty; 
      #region Taking folders from root folder 
       DirectoryInfo[] DI = new DirectoryInfo(directory).GetDirectories("*.*", SearchOption.AllDirectories); 
       foreach (DirectoryInfo D1 in DI) 
       { 

        // the directory you need to zip 
        filenames = Directory.GetFiles(D1.FullName); 
        if (D1.ToString() == "backup") 
        { 
         filenames = null; 
         continue; 
        } 
        if (dirName == string.Empty) 
        { 
         if (D1.ToString() == "updates" || (D1.Parent).ToString() == "updates" || (D1.Parent).Parent.ToString() == "updates" || ((D1.Parent).Parent).Parent.ToString() == "updates" || (((D1.Parent).Parent).Parent).ToString() == "updates" || ((((D1.Parent).Parent).Parent)).ToString() == "updates") 
         { 
          dirName = D1.ToString(); 
          filenames = null; 
          continue; 
         } 
        } 
        else 
        { 
         if (D1.ToString() == dirName) ; 
        } 
        foreach (string filename in filenames) 
        { 
         FileStream fs = File.OpenRead(filename); 
         byte[] buffer = new byte[fs.Length]; 
         fs.Read(buffer, 0, buffer.Length); 
         ZipEntry entry = new ZipEntry(filename); 
         p.PutNextEntry(entry); 
         p.Write(buffer, 0, buffer.Length); 
         fs.Close(); 
        } 
        filenames = null; 
       } 
       p.SetLevel(5); 
       p.Finish(); 
       p.Close(); 
      #endregion 
    } 
    #endregion 

    #region EXTRACT THE ZIP FILE 
    public bool UnZipFile(string InputPathOfZipFile, string FileName) 
    { 
     bool ret = true; 
     Label1.Text = "Please wait, extracting downloaded file"; 
     string zipDirectory = string.Empty; 
     try 
     { 
      #region If Folder already exist Delete it 
      if (Directory.Exists(Server.MapPath("~/updates/" + FileName))) // server data field 
      { 
       String[] files = Directory.GetFiles(Server.MapPath("~/updates/" + FileName));//server data field 
       foreach (var file in files) 
        File.Delete(file); 
       Directory.Delete(Server.MapPath("~/updates/" + FileName), true);//server data field 
      } 
      #endregion 


      if (File.Exists(InputPathOfZipFile)) 
      { 
       string baseDirectory = Path.GetDirectoryName(InputPathOfZipFile); 

       using (ZipInputStream ZipStream = new 

       ZipInputStream(File.OpenRead(InputPathOfZipFile))) 
       { 
        ZipEntry theEntry; 
        while ((theEntry = ZipStream.GetNextEntry()) != null) 
        { 
         if (theEntry.IsFile) 
         { 
          if (theEntry.Name != "") 
          { 
           string directoryName = theEntry.Name.Substring(theEntry.Name.IndexOf(FileName)); // server data field 

           string[] DirectorySplit = directoryName.Split('\\'); 
           for (int i = 0; i < DirectorySplit.Length - 1; i++) 
           { 
            if (zipDirectory != null || zipDirectory != "") 
             zipDirectory = zipDirectory + @"\" + DirectorySplit[i]; 
            else 
             zipDirectory = zipDirectory + DirectorySplit[i]; 
           } 
           string first = Server.MapPath("~/updates") + @"\" + zipDirectory; 
           if (!Directory.Exists(first)) 
            Directory.CreateDirectory(first); 


           string strNewFile = @"" + baseDirectory + @"\" + directoryName; 


           if (File.Exists(strNewFile)) 
           { 
            continue; 
           } 
           zipDirectory = string.Empty; 

           using (FileStream streamWriter = File.Create(strNewFile)) 
           { 
            int size = 2048; 
            byte[] data = new byte[2048]; 
            while (true) 
            { 
             size = ZipStream.Read(data, 0, data.Length); 
             if (size > 0) 
              streamWriter.Write(data, 0, size); 
             else 
              break; 
            } 
            streamWriter.Close(); 
           } 
          } 
         } 
         else if (theEntry.IsDirectory) 
         { 
          string strNewDirectory = @"" + baseDirectory + @"\" + 

          theEntry.Name; 
          if (!Directory.Exists(strNewDirectory)) 
          { 
           Directory.CreateDirectory(strNewDirectory); 
          } 
         } 
        } 
        ZipStream.Close(); 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      ret = false; 
     } 
     return ret; 
    } 
    #endregion 
0

SevenZipSharp là một wrapper quanh tha 7z.dll và LZMA SDK, đó là nguồn mở và miễn phí.

SevenZipCompressor compressor = new SevenZipCompressor(); 
compressor.CompressionLevel = CompressionLevel.Ultra; 
compressor.CompressionMethod = CompressionMethod.Lzma; 
compressor.CompressionMode = CompressionMode.Create; 
compressor.CompressFiles(...); 
Các vấn đề liên quan