Decomprimi i file a livello di codice in .net


221

Sto cercando di decomprimere a livello di codice un file zippato.

Ho provato a utilizzare la System.IO.Compression.GZipStreamclasse in .NET, ma quando viene eseguita la mia app (in realtà un test unitario) ottengo questa eccezione:

System.IO.InvalidDataException: il numero magico nell'intestazione GZip non è corretto. Assicurati di passare in uno stream GZip ..

Ora mi rendo conto che un .zipfile non è uguale a un .gzfile e che GZipnon è lo stesso di Zip.

Tuttavia, poiché sono in grado di estrarre il file facendo doppio clic manualmente sul file zippato e quindi facendo clic sul pulsante "Estrai tutti i file", penso che dovrebbe esserci un modo per farlo anche nel codice.

Pertanto ho provato a utilizzare Process.Start()il percorso del file zippato come input. Questo fa sì che la mia app apra una finestra che mostra i contenuti nel file zippato. Va tutto bene, ma l'app verrà installata su un server senza nessuno in giro per fare clic sul pulsante "Estrai tutti i file".

Quindi, come posso ottenere la mia app per estrarre i file nei file compressi?

O c'è un altro modo per farlo? Preferisco farlo nel codice, senza scaricare librerie o app di terze parti; il dipartimento di sicurezza non è troppo fantasioso ...


12
Il tuo dipartimento di sicurezza è più felice che tu scriva il tuo codice per qualcosa di diverso dall'uso di una libreria che è stata sottoposta a debug e presumibilmente vista da molti occhi? Puoi usare una libreria E "fallo nel codice" (ottieni il sorgente e compila tu stesso) ma vedo reinventare la ruota come un problema più grande di qualsiasi problema di sicurezza causato dall'uso di una vera e propria libreria.
Jared Updike,

10
@Jared - Quando il management ha un'idea in testa ...
Steven Evers,

4
Il reparto sicurezza ha meno rischi se si ottiene un prodotto di terze parti. Basta scaricare dotnetzip e rinominarlo "[inserire il nome dell'azienda] .ziplibrary.dll"
Simon

Risposte:


59

Abbiamo utilizzato SharpZipLib con successo su molti progetti. So che è uno strumento di terze parti, ma il codice sorgente è incluso e potrebbe fornire alcune informazioni se si sceglie di reinventare la ruota qui.


3
Ho provato ad usare SharpZipLib e ha funzionato bene. Immagino che dovrò vedere se il divieto contro libs e aps di terze parti è una regola rigorosa o più di una linea guida.
Petteri,

10
Non conosco la tua azienda, ma la mia esperienza è sempre stata che è possibile ottenere un'eccezione a quel tipo di regola se si scrive una descrizione del business case del motivo per cui si desidera l'eccezione. Indica i risparmi sui costi rispetto al fai-da-te, nonché il fatto che la fonte può essere esaminata. Come fallback, puoi spesso ottenere il permesso di usare il sorgente anche se non ti permetteranno di usare la dll - quindi compilala da solo (o almeno le parti che devi effettivamente usare ...).
RolandTumble

Non è necessario utilizzare librerie esterne per decomprimere i file zip, è possibile utilizzare Shell32 da System32. Si prega di consultare stackoverflow.com/a/43066281/948694
arturn

490

Con .NET 4.5 ora puoi decomprimere i file usando il 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);
    }
  }
}

Il codice precedente è stato preso direttamente dalla documentazione di Microsoft: http://msdn.microsoft.com/en-us/library/ms404280(v=vs.110).aspx

ZipFileè contenuto nell'assieme System.IO.Compression.FileSystem. (Grazie nateirvin ... vedi commento sotto)


118
A proposito, ZipFileè contenuto nell'assieme System.IO.Compression.FileSystem.
nateirvin,

73
Ciò significa che è necessario aggiungere un riferimento DLL all'assembly del framework System.IO.Compression.FileSystem.dll.
Chris Schiffhauer,

che dire dei file .rar. sopra il codice non riesce a estrarre i file .rar.
Raghu,

1
Ho provato questo nel mio API web core asp.net, ha letto bene la prima voce, ma alla seconda voce dà sempre errore A local file header is corrupt. Qualche dubbio su questo?
SoftSan,

Lo stesso con @SoftSan. Ho anche avuto quell'errore. Cosa fare?
Ricco

101

Per .Net 4.5+

Non è sempre desiderato scrivere il file non compresso sul disco. Come sviluppatore ASP.Net, dovrei giocherellare con le autorizzazioni per concedere i diritti alla mia applicazione di scrivere sul filesystem. Lavorando con i flussi in memoria, posso eludere tutto ciò e leggere direttamente i file:

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

In alternativa, puoi comunque scrivere il file decompresso sul disco chiamando ExtractToFile():

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

Per usare la ZipArchiveclasse, dovrai aggiungere un riferimento allo System.IO.Compressionspazio dei nomi e a System.IO.Compression.FileSystem.


8
MSFT ha impiegato veramente 4.5+ per aggiungere un decompressore nativo?
John Peters,

2
@JohnPeters GZipStream è stato aggiunto in .Net 2.0 ( msdn.microsoft.com/en-us/library/… ). Tuttavia, non ha reso facile lavorare con più file in un archivio in memoria. Il nuovo ZipArchiveoggetto si adatta perfettamente al conto.
Mister Epic,

1
Questa è un'alternativa particolarmente buona perché consente di decomprimere senza utilizzare il file system (nel mio caso sto lavorando con risorse incorporate) e non è un'estensione di terze parti.
ANeves

1
Perché dovrei usare un foreachciclo ExtractToFilequando posso semplicemente usare ZipFile.ExtractToDirectory(inputFile, outputDir);Qual è il vantaggio del primo metodo?
The Fluffy Robot

1
in .NET 4.6.1 non riesco a ottenere "ZipArchive" da "System.IO.Compression.FileSystem", qualche idea?
Ravi Anand,

55

File DLL esterni gratuiti e non disponibili. Tutto è in un unico file CS. Un download è solo il file CS, un altro download è un esempio molto facile da capire. L'ho provato oggi e non riesco a credere quanto sia stata semplice l'installazione. Ha funzionato al primo tentativo, nessun errore, niente di niente.

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


Parlato troppo presto! Voglio gonfiare immediatamente i file da un flusso di download http. Questo non funziona dal momento che sta usando le operazioni di ricerca sullo stream :( Bene, grazie al codice sorgente posso scrivere il mio ZipStream ora ...
oyophant

la migliore soluzione al mio problema, dal momento che sto scrivendo un'app di aggiornamento e non posso coinvolgere alcuna DLL nel processo di estrazione da allora dovrei aggiornare anche quelli .... questo è buono. Grazie!
Niklas,

27

Utilizzare la libreria DotNetZip su http://www.codeplex.com/DotNetZip

libreria di classi e set di strumenti per manipolare i file zip. Usa VB, C # o qualsiasi linguaggio .NET per creare, estrarre o aggiornare facilmente i file zip ...

DotNetZip funziona su PC con .NET Framework completo e funziona anche su dispositivi mobili che utilizzano .NET Compact Framework. Crea e leggi file zip in VB, C # o qualsiasi linguaggio .NET o qualsiasi ambiente di scripting ...

Se tutto ciò che desideri è una migliore classe DeflateStream o GZipStream in sostituzione di quella integrata nel .NET BCL, anche DotNetZip ha questo. DeflateStream e GZipStream di DotNetZip sono disponibili in un assembly autonomo, basato su una porta .NET di Zlib. Questi flussi supportano i livelli di compressione e offrono prestazioni molto migliori rispetto alle classi integrate. C'è anche uno ZlibStream per completare il set (RFC 1950, 1951, 1952) ...


1
Hmmm ... Ma questa è una libreria di terze parti!
Petteri,

30
Quanto sei molto attento di te. A meno che tu non abbia voglia di passare diversi mesi a implementare il tuo lettore di file Zip, è la tua migliore opzione.
Sam Axe

Questo è molto meglio di SharpZipLib
Kugel

5
Mi stai facendo domande su una risposta che ha quasi 5 anni. Fare qualche ricerca. Sono sicuro che troverai una risposta.
Sam Axe

2
@PhilCooper Questa è una domanda molto antica che consiglio di utilizzare System.IO.Compression.ZipFile integrato. IIRC Ho avuto davvero brutte esperienze con SharpZipLib in passato sulla base della mia esperienza nella produzione di migliaia di zip al volo.
Kugel,

9
String ZipPath = @"c:\my\data.zip";
String extractPath = @"d:\\myunzips";
ZipFile.ExtractToDirectory(ZipPath, extractPath);

Per utilizzare la classe ZipFile, è necessario aggiungere un riferimento all'assembly System.IO.Compression.FileSystem nel progetto



2

I file zip standard normalmente usano l'algoritmo deflate.

Per estrarre i file senza utilizzare librerie di terze parti utilizzare DeflateStream. Avrai bisogno di maggiori informazioni sul formato di archivio dei file zip poiché Microsoft fornisce solo l'algoritmo di compressione.

Puoi anche provare a usare zipfldr.dll. È la libreria di compressione di Microsoft (cartelle compresse dal menu Invia a). Sembra essere una libreria com ma non è documentata. Potresti riuscire a farlo funzionare per te attraverso la sperimentazione.


Sto provando la classe DeflateStream. Questa volta ottengo System.IO.InvalidDataException: la lunghezza del blocco non corrisponde al suo complemento ..
Petteri,

Come ho detto sopra, Microsoft ha fornito solo l'algoritmo. Avrai bisogno di informazioni anche sul formato dell'archivio zip. en.wikipedia.org/wiki/ZIP_(file_format) dovrebbe iniziare. Vedi i riferimenti in fondo alla pagina per i collegamenti a informazioni più dettagliate.
Kenneth Cochran,

2
Mi sono anche imbattuto in System.IO.Packaging.Package in .NET 3.5. Sembra che potrebbe fare il trucco anche se non è molto intuitivo.
Kenneth Cochran,

2

Lo uso per comprimere o decomprimere più file. Il materiale Regex non è richiesto, ma lo uso per modificare il timbro della data e rimuovere i caratteri di sottolineatura indesiderati. Uso la stringa vuota nella stringa Compress >> zipPath per aggiungere un prefisso a tutti i file, se necessario. Inoltre, di solito commento Compress () o Decompress () in base a ciò che sto facendo.

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);
            }
        }


    }
}

Questo richiede dot net 4.5 - solo una nota come hanno notato altri che hanno risposto con ZipFile e sto ancora usando 3.5.
Thronk,

2

Questo lo farà System.IO.Compression.ZipFile.ExtractToDirectory(ZipName, ExtractToPath)


1

Da qui :

Gli oggetti GZipStream compressi scritti in un file con estensione .gz possono essere decompressi utilizzando molti strumenti di compressione comuni; tuttavia, questa classe non fornisce intrinsecamente funzionalità per l'aggiunta o l'estrazione di file dagli archivi .zip.


1

Puoi fare tutto in .NET 3.5 usando DeflateStream. Ciò che manca in .NET 3.5 è la capacità di elaborare le sezioni di intestazione del file utilizzate per organizzare i file compressi. PKWare ha pubblicato queste informazioni, che è possibile utilizzare per elaborare il file zip dopo aver creato le strutture utilizzate. Non è particolarmente oneroso ed è una buona pratica nella costruzione di strumenti senza l'utilizzo di codice di terze parti.

Non è una risposta a una riga, ma è completamente fattibile se sei disposto e in grado di prenderti il ​​tempo da solo. Ho scritto un corso per farlo in un paio d'ore e quello che ho ottenuto è la possibilità di comprimere e decomprimere i file usando solo .NET 3.5.


0

Ho scoperto questo (pacchetto Unzip su NuGet) oggi, da quando ho riscontrato un grosso bug in DotNetZip, e mi sono reso conto che non è stato fatto molto lavoro su DotNetZip negli ultimi due anni.

Il pacchetto Unzip è snello e ha fatto il mio lavoro - non aveva il bug di DotNetZip. Inoltre, era un file ragionevolmente piccolo, basato sul Microsoft BCL per la decompressione effettiva. Potrei facilmente apportare le modifiche di cui avevo bisogno (per essere in grado di tenere traccia dei progressi durante la decompressione). Lo consiglio.


0

Da Incorpora risorse:

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

0

Fino ad ora, stavo usando i processi cmd per estrarre un file .iso, copiarlo in un percorso temporaneo dal server ed estratto su una chiavetta USB. Recentemente ho scoperto che funziona perfettamente con .iso che sono meno di 10 GB. Per un iso come 29Gb questo metodo si blocca in qualche modo.

    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

è possibile utilizzare il codice della riga di comando Info-unzip. È sufficiente scaricare unzip.exe dal sito Web ufficiale 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; }
    }        
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.