web-dev-qa-db-fra.com

Décompressez les fichiers par programme dans .net

J'essaie de décompresser par programmation un fichier compressé.

J'ai essayé d'utiliser la classe System.IO.Compression.GZipStream dans .NET, mais lorsque mon application est exécutée (en réalité un test unitaire), je reçois cette exception: 

System.IO.InvalidDataException: le nombre magique dans l'en-tête GZip n'est pas correct. Assurez-vous de passer dans un flux GZip.

Je réalise maintenant qu'un fichier .Zip n'est pas identique à un fichier .gz et que GZip n'est pas identique à Zip

Cependant, étant donné que je peux extraire le fichier en double-cliquant manuellement sur le fichier zippé puis en cliquant sur le bouton "Extraire tous les fichiers", je pense qu'il devrait également être possible de le faire dans le code. 

J'ai donc essayé d'utiliser Process.Start() avec le chemin d'accès au fichier compressé en tant qu'entrée. Cela amène mon application à ouvrir une fenêtre affichant le contenu du fichier compressé. Tout va bien, mais l'application sera installée sur un serveur avec personne pour cliquer sur le bouton "Extraire tous les fichiers". 

Alors, comment puis-je obtenir mon application pour extraire les fichiers dans les fichiers compressés?

Ou y a-t-il un autre moyen de le faire? Je préfère le faire dans le code, sans télécharger aucune bibliothèque ou application tierce; le service de sécurité n'a pas trop envie de ça ...

189
Petteri

Nous avons utilisé SharpZipLib avec succès sur de nombreux projets. Je sais que c'est un outil tiers, mais le code source est inclus et pourrait vous éclairer si vous décidiez de réinventer la roue.

51
Chris Conway

Avec .NET 4.5, vous pouvez maintenant décompresser des fichiers à l'aide du framework .NET:

using System;
using System.IO;

namespace ConsoleApplication
{
  class Program
  {
    static void Main(string[] args)
    {
      string startPath = @"c:\example\start";
      string zipPath = @"c:\example\result.Zip";
      string extractPath = @"c:\example\extract";

      System.IO.Compression.ZipFile.CreateFromDirectory(startPath, zipPath);
      System.IO.Compression.ZipFile.ExtractToDirectory(zipPath, extractPath);
    }
  }
}

Le code ci-dessus provient directement de la documentation de Microsoft: http://msdn.Microsoft.com/en-us/library/ms404280(v=vs.110).aspx

ZipFile est contenu dans l'assembly System.IO.Compression.FileSystem. (Merci nateirvin ... voir le commentaire ci-dessous)

432
bsara

Pour .Net 4.5+

Il n'est pas toujours souhaitable d'écrire le fichier non compressé sur le disque. En tant que développeur ASP.Net, je devrais bricoler les autorisations pour accorder des droits à mon application pour écrire dans le système de fichiers. En travaillant avec des flux en mémoire, je peux éviter tout cela et lire les fichiers directement:

using (ZipArchive archive = new ZipArchive(postedZipStream))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
         var stream = entry.Open();
         //Do awesome stream stuff!!
    }
}

Vous pouvez également écrire le fichier décompressé sur le disque en appelant ExtractToFile():

using (ZipArchive archive = ZipFile.OpenRead(pathToZip))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        entry.ExtractToFile(Path.Combine(destination, entry.FullName));
    }
} 

Pour utiliser la classe ZipArchive, vous devez ajouter une référence à l'espace de noms System.IO.Compression.

69
Mister Epic

Gratuit et aucun fichier externe DLL. Tout est dans un fichier CS. Un téléchargement n'est que le fichier CS, un autre est un exemple très facile à comprendre. Juste essayé aujourd'hui et je ne peux pas croire à quel point la configuration était simple. Cela a fonctionné au premier essai, pas d'erreurs, pas de rien.

https://github.com/jaime-olivares/zipstorer

49
Lukas

Utilisez la bibliothèque DotNetZip à l’adresse http://www.codeplex.com/DotNetZip

bibliothèque de classes et jeu d'outils permettant de manipuler des fichiers Zip. Utilisez VB, C # ou n’importe quel langage .NET pour créer, extraire ou mettre à jour facilement des fichiers Zip ...

DotNetZip fonctionne sur les PC dotés de l'intégralité du .NET Framework et fonctionne également sur les appareils mobiles utilisant le .NET Compact Framework. Créez et lisez des fichiers Zip en VB, C #, ou n’importe quel langage .NET, ou n’importe quel environnement de script ...

Si tout ce que vous voulez, c'est une meilleure classe DeflateStream ou GZipStream pour remplacer celle intégrée dans le BCL .NET, DotNetZip l'a également. DeflateStream et GZipStream de DotNetZip sont disponibles dans un assembly autonome, basé sur un port .NET de Zlib. Ces flux prennent en charge les niveaux de compression et offrent des performances bien meilleures que celles des classes intégrées. Il existe également un flux ZlibStream pour compléter l'ensemble (RFC 1950, 1951, 1952) ...

27
Sam Axe
String ZipPath = @"c:\my\data.Zip";
String extractPath = @"d:\\myunzips";
ZipFile.ExtractToDirectory(ZipPath, extractPath);

Pour utiliser la classe ZipFile, vous devez ajouter une référence à l’assembly System.IO.Compression.FileSystem dans votre projet.

8
Mahadev Mane

Les fichiers Zip standard utilisent normalement l'algorithme deflate.

Pour extraire des fichiers sans utiliser de bibliothèques tierces, utilisez DeflateStream. Vous aurez besoin d'un peu plus d'informations sur le format d'archive de fichier Zip, car Microsoft ne fournit que l'algorithme de compression.

Vous pouvez également essayer d’utiliser zipfldr.dll. Il s'agit de la bibliothèque de compression de Microsoft (dossiers compressés du menu Envoyer à). Il semble que ce soit une bibliothèque mais ce n'est pas documenté. Vous pourrez peut-être le faire fonctionner pour vous grâce à l'expérimentation.

2
Kenneth Cochran

Cela le fera System.IO.Compression.ZipFile.ExtractToDirectory(ZipName, ExtractToPath)

1
Ilya Kochetov

J'utilise ceci pour compresser ou décompresser plusieurs fichiers. Le contenu Regex n’est pas obligatoire, mais je l’utilise pour modifier l’horodatage et supprimer les traits de soulignement indésirables. J'utilise la chaîne vide de la chaîne Compress >> zipPath pour préfixer quelque chose à tous les fichiers si nécessaire. De plus, je commente habituellement Compress () ou Decompress () en fonction de ce que je fais.

using System;
using System.IO.Compression;
using System.IO;
using System.Text.RegularExpressions;

namespace ZipAndUnzip
{
    class Program
    {
        static void Main(string[] args)
        {
            var directoryPath = new DirectoryInfo(@"C:\your_path\");

            Compress(directoryPath);
            Decompress(directoryPath);
        }

        public static void Compress(DirectoryInfo directoryPath)
        {
            foreach (DirectoryInfo directory in directoryPath.GetDirectories())
            {
                var path = directoryPath.FullName;
                var newArchiveName = Regex.Replace(directory.Name, "[0-9]{8}", "20130913");
                newArchiveName = Regex.Replace(newArchiveName, "[_]+", "_");
                string startPath = path + directory.Name;
                string zipPath = path + "" + newArchiveName + ".Zip";

                ZipFile.CreateFromDirectory(startPath, zipPath);
            }

        }

        public static void Decompress(DirectoryInfo directoryPath)
        {
            foreach (FileInfo file in directoryPath.GetFiles())
            {
                var path = directoryPath.FullName;
                string zipPath = path + file.Name;
                string extractPath = Regex.Replace(path + file.Name, ".Zip", "");

                ZipFile.ExtractToDirectory(zipPath, extractPath);
            }
        }


    }
}
1
Phyllip Hamby

Vous pouvez tout faire dans .NET 3.5 en utilisant DeflateStream. Ce qui manque dans .NET 3.5, c'est la possibilité de traiter les sections d'en-tête de fichier utilisées pour organiser les fichiers compressés. PKWare a publié ces informations, que vous pouvez utiliser pour traiter le fichier Zip après avoir créé les structures utilisées. Ce n'est pas particulièrement onéreux et c'est une bonne pratique pour la construction d'outils sans utiliser de code tiers.

Ce n'est pas une réponse à une ligne, mais c'est tout à fait faisable si vous êtes prêt et capable de prendre le temps vous-même. J'ai écrit une classe pour faire cela en quelques heures et ce que j'ai tiré de cela est la possibilité de compresser et décompresser des fichiers en utilisant .NET 3.5 uniquement.

1
Michael Blake

De ici :

Objets GZipStream compressés écrits dans un fichier avec une extension .gz peut être décompressé en utilisant de nombreuses communes outils de compression; cependant, cette classe ne fournit pas intrinsèquement fonctionnalité pour ajouter des fichiers à ou extraire des fichiers d’archives .Zip.

1
RedWolves

Jusqu'à présent, j'utilisais les processus cmd afin d'extraire un fichier .iso, de le copier dans un chemin temporaire du serveur et de l'extraire sur une clé USB. Récemment, j'ai constaté que cela fonctionnait parfaitement avec les .iso de moins de 10 Go. Pour une iso comme 29Gb, cette méthode reste bloquée.

    public void ExtractArchive()
    {
        try
        {

            try
            {
                Directory.Delete(copyISOLocation.OutputPath, true); 
            }
            catch (Exception e) when (e is IOException || e is UnauthorizedAccessException)
            {
            }

            Process cmd = new Process();
            cmd.StartInfo.FileName = "cmd.exe";
            cmd.StartInfo.RedirectStandardInput = true;
            cmd.StartInfo.RedirectStandardOutput = true;
            cmd.StartInfo.CreateNoWindow = true;
            cmd.StartInfo.UseShellExecute = false;
            cmd.StartInfo.WindowStyle = ProcessWindowStyle.Normal;

            //stackoverflow
            cmd.StartInfo.Arguments = "-R";

            cmd.Disposed += (sender, args) => {
                Console.WriteLine("CMD Process disposed");
            };
            cmd.Exited += (sender, args) => {
                Console.WriteLine("CMD Process exited");
            };
            cmd.ErrorDataReceived += (sender, args) => {
                Console.WriteLine("CMD Process error data received");
                Console.WriteLine(args.Data);
            };
            cmd.OutputDataReceived += (sender, args) => {
                Console.WriteLine("CMD Process Output data received");
                Console.WriteLine(args.Data);
            };

            //stackoverflow


            cmd.Start();

            cmd.StandardInput.WriteLine("C:");
            //Console.WriteLine(cmd.StandardOutput.Read());
            cmd.StandardInput.Flush();

            cmd.StandardInput.WriteLine("cd C:\\\"Program Files (x86)\"\\7-Zip\\");
            //Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            cmd.StandardInput.Flush();

            cmd.StandardInput.WriteLine(string.Format("7z.exe x -o{0} {1}", copyISOLocation.OutputPath, copyISOLocation.TempIsoPath));
            //Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            cmd.StandardInput.Flush();
            cmd.StandardInput.Close();
            cmd.WaitForExit();
            Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            Console.WriteLine(cmd.StandardError.ReadToEnd());
0
Răzvan Bălan

vous pouvez utiliser Info-unzip ligne de commande cod.Vous avez seulement besoin de télécharger unzip.exe à partir du site officiel Info-unzip.

 internal static void Unzip(string sorcefile)
    {
        try
        {
            AFolderFiles.AFolderFilesDelete.DeleteFolder(TempBackupFolder); // delete old folder   
            AFolderFiles.AFolderFilesCreate.CreateIfNotExist(TempBackupFolder); // delete old folder   
           //need to Command command also to export attributes to a Excel file
            System.Diagnostics.Process process = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; // window type
            startInfo.FileName = UnzipExe;
            startInfo.Arguments = sorcefile + " -d " + TempBackupFolder;
            process.StartInfo = startInfo;
            process.Start();
            //string result = process.StandardOutput.ReadToEnd();
            process.WaitForExit();
            process.Dispose();
            process.Close();
        }
        catch (Exception ex){ throw ex; }
    }        
0
Arun kumar

J'ai découvert l'existence de celui-ci (package Unzip sur NuGet) aujourd'hui, car j'ai rencontré un bogue difficile dans DotNetZip et j'ai réalisé que peu de travail avait été fait sur DotNetZip ces deux dernières années.

Le paquet Unzip est mince et il a fait le travail pour moi - il n’avait pas le bogue de DotNetZip. En outre, il s’agissait d’un fichier relativement petit, reposant sur la BCL de Microsoft pour la décompression proprement dite. Je pouvais facilement faire les ajustements dont j'avais besoin (pour pouvoir suivre les progrès tout en décompressant). Je le recommande.

0
Per Lundberg

De Ressources Embed:

using (Stream _pluginZipResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(programName + "." + "filename.Zip"))
{
    using (ZipArchive Zip = new ZipArchive(_pluginZipResourceStream))
    {
        Zip.ExtractToDirectory(Application.StartupPath);
    }
}
0
Steve Rousseau