Come creo archivi 7-Zip con .NET?


101

Come posso creare archivi 7-Zip dalla mia applicazione console C #? Devo essere in grado di estrarre gli archivi utilizzando il normale programma 7-Zip ampiamente disponibile .


Ecco i miei risultati con gli esempi forniti come risposte a questa domanda

  • "Espellere" a 7z.exe: questo è l'approccio più semplice ed efficace e posso confermare che funziona bene . Come menzionato da workmad3 , devo solo garantire che 7z.exe sia installato su tutte le macchine di destinazione, cosa che posso garantire.
  • 7Zip nella compressione della memoria : si riferisce alla compressione dei cookie "in memoria" prima dell'invio al client; questo metodo sembra alquanto promettente. I metodi wrapper (che racchiudono l' SDK LZMA ) restituiscono il tipo byte[]. Quando scrivo l' byte[]array su un file, non riesco a estrarlo utilizzando 7-Zip ( File.7z is not supported archive).
  • 7zSharp Wrapper (trovato su CodePlex): include 7z exe / LZMA SDK . Ho fatto riferimento al progetto dalla mia app e ha creato con successo alcuni file di archivio, ma non sono riuscito a estrarre i file utilizzando il normale programma 7-Zip ( File.7z is not supported archive).
  • 7Zip SDK aka LZMA SDK - Immagino di non essere abbastanza intelligente da capire come usarlo (motivo per cui ho pubblicato qui) ... Qualsiasi esempio di codice funzionante che dimostri la creazione di un archivio 7zip che può essere estratto dal regolare programma 7zip?
  • CodeProject C # (.NET) Interfaccia per DLL di archivio 7-Zip - supporta solo l'estrazione da archivi 7zip ... Devo crearli!
  • SharpZipLib - Secondo le loro FAQ , SharpZipLib non supporta 7zip.

32
Non scrivere da Google quando tutti i link provengono dal mio post qui sotto. Non molto rispettoso per le persone che si sono prese il tempo per cercare per te alcune soluzioni.
Patrick Desjardins

3
So che questo post è vecchio, ma ho visto un progetto chiamato SevenZipSharp nella mia ricerca oggi. sevenzipsharp.codeplex.com
Timmerz

12
Solo un avvertimento per i futuri lettori. SevenZipSharp sembra essere un abbandono. Ad oggi l'ultima versione stabile (0.64) è stata rilasciata nell'agosto 2010 con alcuni fastidiosi problemi di multithreading (secondo le segnalazioni di bug). Da allora sono stati pubblicati solo pochi commit del codice sorgente .
Anttu

Risposte:


28

Se puoi garantire che l'app 7-zip verrà installata (e nel percorso) su tutti i computer di destinazione, puoi eseguire l'offload chiamando l'app della riga di comando 7z. Non è la soluzione più elegante ma è il minimo lavoro.


7
In realtà spediamo l'utilità della riga di comando 7z con i nostri binari e eseguiamo la shell. Funziona davvero bene per noi.
David Mohundro

79

Esempio di cookie EggCafe 7Zip Questo è un esempio (cookie zippato) con la DLL di 7Zip.

CodePlex Wrapper Questo è un progetto open source che deforma la funzione di compressione di 7z.

7Zip SDK L' SDK ufficiale per 7zip (C, C ++, C #, Java) <--- Il mio suggerimento

Libreria zip .Net di SharpDevelop.net

Esempio di CodeProject con 7zip

SharpZipLib Molti zippare


Fatto e ho aggiunto anche un utile progetto open source.
Patrick Desjardins

1
LOL? Cambia il cookie con una stringa ... un file o qualsiasi altra cosa ... lol?
Patrick Desjardins

1
No, voglio solo vedere se qualcuno ha trovato un esempio funzionante ... Grazie per la tua ricerca, ma nessuno dei link che hai fornito è stato in grado di condurmi a qualcosa che funziona.
Seibar,

2
Devo ammettere che nessuno ha un codice che puoi copiare e incollare. L'SDK è quello con tutte le risposte, ma ci vuole tempo e impegno per avere qualcosa che funzioni. Posso capire che non vuoi farlo. Buona giornata.
Patrick Desjardins,

3
Ad ogni modo, suggerisco di rimuovere i riferimenti SharpDevelop / SharpZipLib, poiché entrambi fanno riferimento allo stesso e non supportano 7-Zip. Seibar ha chiesto esplicitamente 7z. Sto anche cercando soluzioni 7z perché ShaprZipLib non ha funzionato con l'archivio e ha trovato questo thread. ShaprZipLib è un suggerimento fuorviante!
Onsokumaru

25

SevenZipSharp è un'altra soluzione. Crea archivi 7-zip ...


7
Questo post di markhor è in realtà del creatore del progetto SevenZipSharp. SevenZipSharp consente l'accesso programmatico alla dll 7Zip, rendendola molto completa. Ho trovato LZMA SDK di basso livello e difficile da capire. SevenZipSharp, al contrario, è ben documentato, facile da usare e ha molti utilizzi di esempio nel suo progetto di prova. Utilizzando gli esempi, ho potuto comprimere e decomprimere rapidamente utilizzando file o memoria.
John Wigger

4
SevenZipSharp sembra essere abbandonato. Vedi il mio commento precedente nella domanda.
Anttu

SevenZipSharp è lento. Al momento la soluzione più consigliata è utilizzare Process.Start ("7z.exe ......)
klm_

24

Ecco un esempio funzionante completo utilizzando SevenZip SDK in C #.

Scriverà e leggerà i file 7zip standard creati dall'applicazione Windows 7zip.

PS. L'esempio precedente non sarebbe mai stato decompresso perché non ha mai scritto le informazioni sulla proprietà richieste all'inizio del file.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SevenZip.Compression.LZMA;
using System.IO;
using SevenZip;

namespace VHD_Director
{
    class My7Zip
    {
        public static void CompressFileLZMA(string inFile, string outFile)
        {
            Int32 dictionary = 1 << 23;
            Int32 posStateBits = 2;
            Int32 litContextBits = 3; // for normal files
            // UInt32 litContextBits = 0; // for 32-bit data
            Int32 litPosBits = 0;
            // UInt32 litPosBits = 2; // for 32-bit data
            Int32 algorithm = 2;
            Int32 numFastBytes = 128;

            string mf = "bt4";
            bool eos = true;
            bool stdInMode = false;


            CoderPropID[] propIDs =  {
                CoderPropID.DictionarySize,
                CoderPropID.PosStateBits,
                CoderPropID.LitContextBits,
                CoderPropID.LitPosBits,
                CoderPropID.Algorithm,
                CoderPropID.NumFastBytes,
                CoderPropID.MatchFinder,
                CoderPropID.EndMarker
            };

            object[] properties = {
                (Int32)(dictionary),
                (Int32)(posStateBits),
                (Int32)(litContextBits),
                (Int32)(litPosBits),
                (Int32)(algorithm),
                (Int32)(numFastBytes),
                mf,
                eos
            };

            using (FileStream inStream = new FileStream(inFile, FileMode.Open))
            {
                using (FileStream outStream = new FileStream(outFile, FileMode.Create))
                {
                    SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
                    encoder.SetCoderProperties(propIDs, properties);
                    encoder.WriteCoderProperties(outStream);
                    Int64 fileSize;
                    if (eos || stdInMode)
                        fileSize = -1;
                    else
                        fileSize = inStream.Length;
                    for (int i = 0; i < 8; i++)
                        outStream.WriteByte((Byte)(fileSize >> (8 * i)));
                    encoder.Code(inStream, outStream, -1, -1, null);
                }
            }

        }

        public static void DecompressFileLZMA(string inFile, string outFile)
        {
            using (FileStream input = new FileStream(inFile, FileMode.Open))
            {
                using (FileStream output = new FileStream(outFile, FileMode.Create))
                {
                    SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();

                    byte[] properties = new byte[5];
                    if (input.Read(properties, 0, 5) != 5)
                        throw (new Exception("input .lzma is too short"));
                    decoder.SetDecoderProperties(properties);

                    long outSize = 0;
                    for (int i = 0; i < 8; i++)
                    {
                        int v = input.ReadByte();
                        if (v < 0)
                            throw (new Exception("Can't Read 1"));
                        outSize |= ((long)(byte)v) << (8 * i);
                    }
                    long compressedSize = input.Length - input.Position;

                    decoder.Code(input, output, compressedSize, outSize, null);
                }
            }
        }

        public static void Test()
        {
            CompressFileLZMA("DiscUtils.pdb", "DiscUtils.pdb.7z");
            DecompressFileLZMA("DiscUtils.pdb.7z", "DiscUtils.pdb2");
        }
    }
}

15
Nota che questa è pura compressione / decompressione LZMA. Il formato di file 7zip è un livello sopra questo che consente di impacchettare più file insieme ai nomi / percorsi dei file e altri metdati dei file.
redcalx

1
@redcalx è corretto. Qualcuno ha idea di come elaborare lo strato superiore 7zip? Fare riferimento a un altro post SO sarebbe fantastico :)
Christopher J Smith

8

Ho usato l'SDK.

per esempio:

using SevenZip.Compression.LZMA;
private static void CompressFileLZMA(string inFile, string outFile)
{
   SevenZip.Compression.LZMA.Encoder coder = new SevenZip.Compression.LZMA.Encoder();

   using (FileStream input = new FileStream(inFile, FileMode.Open))
   {
      using (FileStream output = new FileStream(outFile, FileMode.Create))
      {
          coder.Code(input, output, -1, -1, null);
          output.Flush();
      }
   }
}

7
E come decomprimerai il file? Ho provato a fare lo stesso usando SevenZip.Compression.LZMA.Decoder e chiamandolo con Code (stream1, stream2, -1, -1, null); Ciò ha fornito un'eccezione di dati dal framework.
Karsten

3
 string zipfile = @"E:\Folderx\NPPES.zip";
 string folder = @"E:\TargetFolderx";

 ExtractFile(zipfile,folder);
public void ExtractFile(string source, string destination)
        {
            // If the directory doesn't exist, create it.
            if (!Directory.Exists(destination))
                Directory.CreateDirectory(destination);

            //string zPath = ConfigurationManager.AppSettings["FileExtactorEXE"];
          //  string zPath = Properties.Settings.Default.FileExtactorEXE; ;

            string zPath=@"C:\Program Files\7-Zip\7zG.exe";

            try
            {
                ProcessStartInfo pro = new ProcessStartInfo();
                pro.WindowStyle = ProcessWindowStyle.Hidden;
                pro.FileName = zPath;
                pro.Arguments = "x \"" + source + "\" -o" + destination;
                Process x = Process.Start(pro);
                x.WaitForExit();
            }
            catch (System.Exception Ex) { }
        }

Basta installare 7 zip dall'origine e passare il parametro al metodo.

Grazie. Per favore, come la risposta.


Questo ha funzionato per me in un servizio Windows con 7za.exe
Marco Duindam

1

Uso questo codice

                string PZipPath = @"C:\Program Files\7-Zip\7z.exe";
                string sourceCompressDir = @"C:\Test";
                string targetCompressName = @"C:\Test\abc.zip";
                string CompressName = targetCompressName.Split('\\').Last();
                string[] fileCompressList = Directory.GetFiles(sourceCompressDir, "*.*");

                    if (fileCompressList.Length == 0)
                    {
                        MessageBox.Show("No file in directory", "Important Message");
                        return;
                    }
                    string filetozip = null;
                    foreach (string filename in fileCompressList)
                    {
                        filetozip = filetozip + "\"" + filename + " ";
                    }

                    ProcessStartInfo pCompress = new ProcessStartInfo();
                    pCompress.FileName = PZipPath;
                    if (chkRequestPWD.Checked == true)
                    {
                        pCompress.Arguments = "a -tzip \"" + targetCompressName + "\" " + filetozip + " -mx=9" + " -p" + tbPassword.Text;
                    }
                    else
                    {
                        pCompress.Arguments = "a -tzip \"" + targetCompressName + "\" \"" + filetozip + "\" -mx=9";
                    }
                    pCompress.WindowStyle = ProcessWindowStyle.Hidden;
                    Process x = Process.Start(pCompress);
                    x.WaitForExit();

1

Installa il pacchetto NuGet chiamato SevenZipSharp.Interop

Poi:

SevenZipBase.SetLibraryPath(@".\x86\7z.dll");
var compressor = new SevenZip.SevenZipCompressor();
var filesToCompress = Directory.GetFiles(@"D:\data\");
compressor.CompressFiles(@"C:\archive\abc.7z", filesToCompress);

Ho provato ad aggiungere file all'archivio 7z esistente con esso e ho ottenuto un archivio danneggiato.
Geografia

1

Alcune informazioni di prova aggiuntive sul codice @Orwellophile utilizzando un file di testo da 17,9 MB.
L'utilizzo dei valori delle proprietà nell'esempio di codice "così com'è" avrà un enorme impatto negativo sulle prestazioni, richiede 14,16 secondi .

Impostando le proprietà come segue si esegue lo stesso lavoro a 3,91 sec (ad esempio l'archivio avrà le stesse informazioni sul contenitore che sono: puoi estrarre e testare l'archivio con 7zip ma non ci sono informazioni sul nome del file)

Nativo 7zip 2 sec.

CoderPropID[] propIDs =  {
  //CoderPropID.DictionarySize,
  //CoderPropID.PosStateBits,
  //CoderPropID.LitContextBits,
  //CoderPropID.LitPosBits,
  //CoderPropID.Algorithm,
  //CoderPropID.NumFastBytes,
  //CoderPropID.MatchFinder,
  CoderPropID.EndMarker
};
object[] properties = {
  //(Int32)(dictionary),
  //(Int32)(posStateBits),
  //(Int32)(litContextBits),
  //(Int32)(litPosBits),
  //(Int32)(algorithm),
  //(Int32)(numFastBytes),
  //mf,
  eos
};

Ho fatto un altro test utilizzando 7zip nativo e un file di backup SQL da 1,2 GB (.bak)
7zip (compressione massima): 1 minuto
LZMA SDK (@Orwellophile con impostazione delle proprietà sopra): 12:26 min :-(
File di output all'incirca della stessa dimensione .

Quindi immagino che userò una soluzione basata sul motore c / c ++, tra cui o chiamare l'eseguibile 7zip da c # o usare squid-box / SevenZipSharp , che è un wrapper attorno al file dll 7zip c / c ++, e sembra per essere il nuovo fork di SevenZipSharp. Non ho testato il wrapper, ma spero che funzioni esattamente come il 7zip nativo. Ma si spera che dia la possibilità di comprimere anche il flusso che ovviamente non è possibile se chiami direttamente l'exe. Altrimenti immagino che non ci sia un vantaggio poltiglia rispetto a chiamare l'exe. Il wrapper ha alcune dipendenze aggiuntive, quindi non renderà il progetto pubblicato "più pulito".

A proposito, sembra che il team .Net Core consideri l'implementazione di LZMA nella classe system.io in .Core ver. 5, sarebbe fantastico!

(So ​​che questo è una specie di commento e non una risposta, ma per essere in grado di fornire lo snippet di codice non potrebbe essere un commento)


0

Il modo più semplice è lavorare con file .zip invece di .7z e utilizzare Dot Net Zip

Quando si disattivano i comandi 7zip per la shell ci sono altri problemi come i privilegi dell'utente, ho avuto problemi con SevenZipSharp.

Private Function CompressFile(filename As String) As Boolean
Using zip As New ZipFile()
    zip.AddFile(filename & ".txt", "")
    zip.Save(filename & ".zip")
End Using

Return File.Exists(filename & ".zip")
End Function

0

SharpCompress è a mio parere una delle librerie di compressione più intelligenti in circolazione . Supporta LZMA (7-zip), è facile da usare e in fase di sviluppo attivo.

Poiché ha già il supporto per lo streaming LZMA, al momento della scrittura purtroppo supporta solo la lettura dell'archivio 7-zip. MA la scrittura in archivio è nella loro lista di cose da fare (vedi readme). Per i lettori futuri: selezionare per ottenere lo stato corrente qui: https://github.com/adamhathcock/sharpcompress/blob/master/FORMATS.md

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.