2009-06-21 7 views
47

Il semble qu'il n'y ait pas de bibliothèque/API intégrée en C# pour décompresser un fichier zip. Je suis à la recherche d'une bibliothèque/API libre (meilleure open source) qui pourrait fonctionner avec .Net 3.5 + VSTS 2008 + C# pour décompresser un fichier zip et extraire tous les fichiers dans un dossier spécifique.recommande une bibliothèque/API pour décompresser le fichier en C#

Une bibliothèque/API ou des échantillons recommandés?

Répondre

2

Si vous voulez utiliser la compression 7-zip, consultez Peter Bromberg EggheadCafe article. Attention: le LZMA source code pour C# n'a pas de commentaires xml (en fait, très peu de commentaires du tout).

16

DotNetZip est facile à utiliser. Voici un échantillon de Décompressez

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

Si vous avez des besoins plus complexes, comme vous voulez choisir-et choisir les entrées à extraire, ou s'il y a des mots de passe, ou si vous voulez contrôler les noms de fichiers des fichiers extraits , ou etc etc etc, il y a beaucoup d'options. Check the help file pour plus d'exemples.

DotNetZip est gratuit et open source.

9

Dans le passé, j'ai utilisé DotNetZip (MS-PL), SharpZipLib (GPL), et le 7ZIP SDK for C# (domaine public). Ils fonctionnent tous très bien et sont open source.

Je choisirais DotNetZip dans cette situation, et voici quelques exemples de code de la C# Examples page:

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

LGPL, pas GPL - la différence est assez grande. –

+0

@Quandary lequel? SharpZipLib est GPL, selon leur site web. –

+0

GPL avec cette exception (le lier statiquement ou dynamiquement avec votre projet n'est pas un travail dérivé de la GPL) = LGPL (ok, la permission de lier statiquement n'est pas dans la LGPL, c'est pourquoi ils l'écrivent comme ceci pour .NET). Franchement, c'est une version plus libérale de la LGPL. –

23

Si tout ce que vous voulez faire est décompresser le contenu d'un fichier dans un dossier, et vous savez que vous ne serez exécuté que sur Windows, vous pouvez utiliser l'objet Windows Shell. J'ai utilisé dynamic de Framework 4.0 dans cet exemple, mais vous pouvez obtenir les mêmes résultats en utilisant Type.InvokeMember.

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

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

destinationFolder.CopyHere(compressedFolderContents); 

Vous pouvez utiliser FILEOP_FLAGS pour contrôler le comportement de la méthode CopyHere.

+1

De loin LA réponse la plus stinkin 'génial à cette question séculaire! Cela nécessite des investissements majeurs. – Joshua

+1

Je suis d'accord avec @joshuam ... – dda

1

Si vous ne voulez pas utiliser un composant externe, voici un code que j'ai développé hier soir en utilisant la classe ZipPackage de .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); 
    } 
} 

choses à noter:

  • L'archive ZIP DOIT avoir un [Content_Types] fichier .xml dans sa racine. Ce n'était pas un problème pour mes besoins car je vais contrôler le zipping de tous les fichiers ZIP qui sont extraits à travers ce code. Pour plus d'informations sur le fichier [Content_Types] .xml, s'il vous plaît se référer à: http://msdn.microsoft.com/en-us/magazine/cc163372.aspx Il existe un exemple de fichier ci-dessous Figure 13 de l'article.

  • Je n'ai pas testé la méthode CopyStream pour m'assurer qu'elle se comporte correctement, comme je l'ai développé à l'origine pour .NET 4.0 en utilisant la méthode 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 est un wrapper autour tha 7z.dll et LZMA SDK, qui est open-source et gratuit.

SevenZipCompressor compressor = new SevenZipCompressor(); 
compressor.CompressionLevel = CompressionLevel.Ultra; 
compressor.CompressionMethod = CompressionMethod.Lzma; 
compressor.CompressionMode = CompressionMode.Create; 
compressor.CompressFiles(...); 
Questions connexes