Comment créer des archives 7-Zip avec .NET?

101

Comment puis-je créer des archives 7-Zip à partir de mon application console C #? J'ai besoin de pouvoir extraire les archives en utilisant le programme 7-Zip standard et largement disponible .


Voici mes résultats avec les exemples fournis en réponse à cette question

  • "Shelling out" à 7z.exe - c'est l'approche la plus simple et la plus efficace, et je peux confirmer que cela fonctionne bien . Comme le mentionne workmad3 , je dois juste garantir que 7z.exe est installé sur toutes les machines cibles, ce que je peux garantir.
  • 7Zip en compression mémoire - cela fait référence à la compression des cookies "en mémoire" avant l'envoi au client; cette méthode semble assez prometteuse. Les méthodes de wrapper (encapsulant le SDK LZMA ) retournent le type byte[]. Lorsque j'écris le byte[]tableau dans un fichier, je ne peux pas l'extraire en utilisant 7-Zip ( File.7z is not supported archive).
  • 7zSharp Wrapper (trouvé sur CodePlex) - cela englobe le SDK 7z exe / LZMA . J'ai référencé le projet à partir de mon application et il a créé avec succès des fichiers d'archive, mais je n'ai pas pu extraire les fichiers à l'aide du programme 7-Zip ( File.7z is not supported archive).
  • 7Zip SDK aka LZMA SDK - Je suppose que je ne suis pas assez intelligent pour comprendre comment l'utiliser (c'est pourquoi j'ai posté ici) ... Tous les exemples de code de travail qui démontrent la création d'une archive 7zip qui peut être extraite par le programme 7zip régulier?
  • Interface CodeProject C # (.NET) pour les DLL d'archives 7-Zip - prend uniquement en charge l'extraction des archives 7zip ... J'ai besoin de les créer!
  • SharpZipLib - Selon leur FAQ , SharpZipLib ne prend pas en charge 7zip.
Seibar
la source
32
N'écrivez pas cela de Google lorsque tous les liens proviennent de mon message ci-dessous. Pas très respectueux des gens qui ont pris le temps de vous chercher des solutions.
Patrick Desjardins
3
Je sais que cet article est ancien, mais j'ai vu un projet appelé SevenZipSharp dans mes recherches aujourd'hui. sevenzipsharp.codeplex.com
Timmerz
12
Juste un mot d'avertissement pour les futurs lecteurs. Le SevenZipSharp semble être abandonware. À partir d'aujourd'hui, la dernière version stable (0.64) a été publiée en août 2010 avec quelques problèmes de multithreading désagréables (selon les rapports de bogue). Seuls quelques commits de code source ont été publiés depuis.
Anttu

Réponses:

28

Si vous pouvez garantir que l'application 7-zip sera installée (et dans le chemin) sur toutes les machines cibles, vous pouvez décharger en appelant l'application de ligne de commande 7z. Ce n'est pas la solution la plus élégante mais c'est le moins de travail.

workmad3
la source
7
En fait, nous livrons l'utilitaire de ligne de commande 7z avec nos binaires et y envoyons un shell. Fonctionne vraiment bien pour nous.
David Mohundro
79

Exemple de cookie EggCafe 7Zip Voici un exemple (cookie zipping) avec la DLL de 7Zip.

CodePlex Wrapper Il s'agit d'un projet open source qui déforme la fonction zipping de 7z.

7Zip SDK Le SDK officiel pour 7zip (C, C ++, C #, Java) <--- Ma suggestion

Bibliothèque zip .Net par SharpDevelop.net

Exemple de CodeProject avec 7zip

SharpZipLib Beaucoup de zips

Patrick Desjardins
la source
C'est fait et j'ai ajouté un projet open source utile aussi.
Patrick Desjardins
1
LOL? Changez le cookie par une chaîne ... un fichier ou autre ... lol?
Patrick Desjardins
1
Non, je veux juste voir si quelqu'un a trouvé un exemple de travail ... Merci pour votre recherche, mais aucun des liens que vous avez fournis n'a pu me conduire à quelque chose qui fonctionne.
Seibar
2
Je dois accepter qu'aucun code ne soit copié et collé. Le SDK est celui avec toutes les réponses, mais il faut du temps et des efforts pour avoir quelque chose qui fonctionne. Je peux comprendre que vous ne vouliez pas le faire. Bonne journée.
Patrick Desjardins
3
Quoi qu'il en soit, je suggère de supprimer les références SharpDevelop / SharpZipLib, car les deux se réfèrent au même et ne prennent pas en charge 7-Zip. Seibar a demandé explicitement 7z. Je recherche également des solutions 7z car ShaprZipLib ne fonctionnait pas avec l'archive et a trouvé ce fil. ShaprZipLib est un indice trompeur!
Onsokumaru
25

SevenZipSharp est une autre solution. Crée des archives 7-zip ...

Markhor
la source
7
Ce message de markhor provient en fait du créateur du projet SevenZipSharp. SevenZipSharp permet un accès par programme à la dll 7Zip, ce qui la rend très complète. J'ai trouvé que le SDK LZMA était de bas niveau et difficile à comprendre. SevenZipSharp, en revanche, est bien documenté, facile à utiliser et présente de nombreux exemples d'utilisation dans son projet de test. En utilisant les exemples, je pourrais rapidement compresser et décompresser en utilisant un fichier ou de la mémoire.
John Wigger
4
SevenZipSharp semble être abandonné. Voir mon commentaire précédent dans la question.
Anttu
SevenZipSharp est lent. Pour le moment, la solution la plus recommandée est d'utiliser Process.Start ("7z.exe ......)
klm_
24

Voici un exemple de travail complet utilisant le SDK SevenZip en C #.

Il écrira et lira les fichiers 7zip standard créés par l'application Windows 7zip.

PS. L'exemple précédent n'allait jamais décompresser car il n'a jamais écrit les informations de propriété requises au début du fichier.

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");
        }
    }
}
Orwellophile
la source
15
Notez qu'il s'agit d'une compression / décompression LZMA pure. Le format de fichier 7zip est une couche au-dessus qui permet de regrouper plusieurs fichiers avec les noms de fichiers / chemins et d'autres métdonnées de fichier.
redcalx
1
@redcalx est correct. Quelqu'un a-t-il une idée de la façon de traiter la couche supérieure 7zip? Une référence à un autre article de SO serait géniale :)
Christopher J Smith
8

J'ai utilisé le sdk.

par exemple:

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();
      }
   }
}
WOPR
la source
7
Et comment allez-vous décompresser le fichier? J'ai essayé de faire la même chose en utilisant SevenZip.Compression.LZMA.Decoder et en l'appelant avec Code (stream1, stream2, -1, -1, null); Cela a donné une exception de données du cadre.
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) { }
        }

Installez simplement 7 zip à partir de la source et passez le paramètre à la méthode.

Merci. Veuillez aimer la réponse.

Vishal Sen
la source
Cela a fonctionné pour moi dans un service Windows avec 7za.exe
Marco Duindam
1

J'utilise ce code

                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();
mode de vie
la source
1

Installez le package NuGet appelé SevenZipSharp.Interop

Ensuite:

SevenZipBase.SetLibraryPath(@".\x86\7z.dll");
var compressor = new SevenZip.SevenZipCompressor();
var filesToCompress = Directory.GetFiles(@"D:\data\");
compressor.CompressFiles(@"C:\archive\abc.7z", filesToCompress);
Fidel
la source
J'ai essayé d'ajouter un fichier à l'archive 7z existante et j'ai obtenu une archive corrompue.
Géographie
1

Quelques informations de test supplémentaires sur le code @Orwellophile utilisant un fichier texte de 17,9 Mo.
L'utilisation des valeurs de propriété dans l'exemple de code "tel quel" aura un impact négatif ÉNORME sur les performances, cela prend 14,16 secondes .

En définissant les propriétés comme suit, effectuez le même travail à 3,91 s (par exemple, l'archive aura les mêmes informations sur le conteneur, à savoir: vous pouvez extraire et tester l'archive avec 7zip mais il n'y a pas d'informations sur le nom de fichier)

7zip natif 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
};

J'ai fait un autre test en utilisant 7zip natif et un fichier de sauvegarde SQL de 1,2 Go (.bak)
7zip (compression maximale): 1 minute
LZMA SDK (@Orwellophile avec le paramètre de propriété ci-dessus): 12:26 min :-(
Outputfile à peu près la même taille .

Je suppose donc que je vais moi-même utiliser une solution basée sur le moteur c / c ++, soit appeler l'exécutable 7zip à partir de c # ou utiliser squid-box / SevenZipSharp , qui est un wrapper autour du fichier dll 7zip c / c ++, et semble être le tout dernier fork de SevenZipSharp. Je n'ai pas testé le wrapper, mais j'espère qu'il fonctionne exactement comme le 7zip natif. Mais j'espère que cela donnera également la possibilité de compresser le flux, ce que vous ne pouvez évidemment pas si vous appelez directement l'exe. Sinon, je suppose qu'il n'y a pas d'avantage à appeler l'exe. L'encapsuleur a quelques dépendances supplémentaires donc il ne rendra pas votre projet publié "plus propre".

Au fait, il semble que l'équipe .Net Core envisage d'implémenter LZMA dans la classe system.io dans .Core ver. 5, ce serait génial!

(Je sais que c'est une sorte de commentaire et non une réponse, mais pour pouvoir fournir l'extrait de code, cela ne peut pas être un commentaire)

MrCalvin
la source
0

Le moyen le plus simple est de travailler avec des fichiers .zip au lieu de .7z et d'utiliser Dot Net Zip

Lors de la rotation des commandes 7zip pour shell, il y a d'autres problèmes tels que les privilèges utilisateur, j'ai eu un problème avec 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
Brent
la source
0

SharpCompress est à mon avis l'une des bibliothèques de compression les plus intelligentes. Il prend en charge LZMA (7-zip), est facile à utiliser et en développement actif.

Comme il prend déjà en charge le streaming LZMA, au moment de l'écriture, il ne prend malheureusement en charge que la lecture d'archives 7-zip. MAIS l'écriture d'archive est sur leur liste de tâches (voir readme). Pour les futurs lecteurs: vérifiez le statut actuel ici: https://github.com/adamhathcock/sharpcompress/blob/master/FORMATS.md

Mario Eis
la source