¿Cómo creo archivos 7-Zip con .NET?

101

¿Cómo puedo crear archivos 7-Zip desde mi aplicación de consola C #? Necesito poder extraer los archivos usando el programa 7-Zip regular y ampliamente disponible .


Aquí están mis resultados con los ejemplos proporcionados como respuestas a esta pregunta

  • "Desgranar" a 7z.exe: este es el método más simple y eficaz, y puedo confirmar que funciona bien . Como menciona workmad3 , solo necesito garantizar que 7z.exe esté instalado en todas las máquinas de destino, lo cual es algo que puedo garantizar.
  • 7Zip en la compresión de la memoria : esto se refiere a comprimir las cookies "en la memoria" antes de enviarlas al cliente; este método parece algo prometedor. Los métodos de envoltura (envolviendo el SDK de LZMA ) devuelven el tipo byte[]. Cuando escribo la byte[]matriz en un archivo, no puedo extraerlo usando 7-Zip ( File.7z is not supported archive).
  • 7zSharp Wrapper (que se encuentra en CodePlex): envuelve el 7z exe / LZMA SDK . Hice referencia al proyecto desde mi aplicación y creó con éxito algunos archivos de almacenamiento, pero no pude extraer los archivos con el programa 7-Zip normal ( File.7z is not supported archive).
  • 7Zip SDK también conocido como LZMA SDK - Supongo que no soy lo suficientemente inteligente como para averiguar cómo usar esto (por eso publiqué aquí) ... Cualquier ejemplo de código que funcione que demuestre la creación de un archivo 7zip que pueda ser extraído por el programa 7zip regular?
  • Interfaz CodeProject C # (.NET) para archivos DLL de archivos 7-Zip : solo admite la extracción de archivos 7zip ... ¡Necesito crearlos!
  • SharpZipLib : según sus preguntas frecuentes , SharpZipLib no es compatible con 7zip.
Seibar
fuente
32
No escriba que es de Google cuando todos los enlaces son de mi publicación a continuación. No es muy respetuoso con las personas que se han tomado el tiempo de buscarte algunas soluciones.
Patrick Desjardins
3
Sé que esta publicación es antigua, pero vi un proyecto llamado SevenZipSharp en mi investigación de hoy. sevenzipsharp.codeplex.com
Timmerz
12
Solo una advertencia para los futuros lectores. SevenZipSharp parece estar abandonado. A partir de hoy, la última versión estable (0.64) se lanzó en agosto de 2010 con algunos problemas desagradables de subprocesos múltiples (según los informes de errores). Desde entonces, solo se han publicado unas pocas confirmaciones de código fuente .
Anttu

Respuestas:

28

workmad3
fuente
7
De hecho, enviamos la utilidad de línea de comandos 7z con nuestros binarios y la utilizamos. Funciona muy bien para nosotros.
David Mohundro
79

Ejemplo de cookie de EggCafe 7Zip Este es un ejemplo (cookie de zip) con la DLL de 7Zip.

CodePlex Wrapper Este es un proyecto de código abierto que deforma la función de compresión de 7z.

7Zip SDK El SDK oficial para 7zip (C, C ++, C #, Java) <--- Mi sugerencia

Biblioteca zip .Net de SharpDevelop.net

Ejemplo de CodeProject con 7zip

SharpZipLib Muchas cremalleras

Patrick Desjardins
fuente
Hecho y agregué un proyecto de código abierto útil también.
Patrick Desjardins
1
LOL? Cambiar la cookie por una cadena ... un archivo o lo que sea ... jajaja?
Patrick Desjardins
1
No, solo quiero ver si a alguien se le ha ocurrido un ejemplo que funcione ... Gracias por su investigación, pero ninguno de los enlaces que proporcionó ha podido llevarme a algo que funcione.
Seibar
2
Tengo que aceptar que ninguno tiene un código que puedas copiar y pegar. El SDK es el que tiene todas las respuestas, pero se necesita algo de tiempo y esfuerzo para tener algo que funcione. Puedo entender que no quieras hacerlo. Que tengas un buen día.
Patrick Desjardins
3
De todos modos, sugiero eliminar las referencias de SharpDevelop / SharpZipLib, ya que ambas hacen referencia a lo mismo y no son compatibles con 7-Zip. Seibar pidió explícitamente 7z. También estoy buscando soluciones 7z porque ShaprZipLib no funcionó con el archivo y encontró este hilo. ¡ShaprZipLib es una pista engañosa!
Onsokumaru
25

SevenZipSharp es otra solución. Crea archivos 7-zip ...

Markhor
fuente
7
Esta publicación de markhor es en realidad del creador del proyecto SevenZipSharp. SevenZipSharp permite el acceso programático a la dll 7Zip, lo que la hace muy completa. Encontré que el SDK de LZMA es de bajo nivel y difícil de entender. SevenZipSharp, por el contrario, está bien documentado, es fácil de usar y tiene muchos usos de muestra en su proyecto de prueba. Usando los ejemplos, pude comprimir y descomprimir rápidamente usando un archivo o memoria.
John Wigger
4
SevenZipSharp parece estar abandonado. Vea mi comentario anterior en la pregunta.
Anttu
SevenZipSharp es lento. Por el momento, la solución más recomendada es utilizar Process.Start ("7z.exe ......)
klm_
24

Aquí hay un ejemplo de trabajo completo usando el SevenZip SDK en C #.

Escribirá y leerá archivos 7zip estándar creados por la aplicación Windows 7zip.

PD. El ejemplo anterior nunca se iba a descomprimir porque nunca escribió la información de propiedad requerida al comienzo del archivo.

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
fuente
15
Tenga en cuenta que esto es pura compresión / descompresión LZMA. El formato de archivo 7zip es una capa por encima de esto que permite empaquetar varios archivos junto con los nombres de archivo / rutas y otros archivos metdata.
redcalx
1
@redcalx es correcto. ¿Alguien tiene idea de cómo procesar la capa superior de 7zip? La referencia a otra publicación de SO sería genial :)
Christopher J Smith
8

Usé el sdk.

p.ej:

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
fuente
7
¿Y cómo descomprimirás el archivo? Intenté hacer lo mismo usando SevenZip.Compression.LZMA.Decoder y llamándolo con Code (stream1, stream2, -1, -1, null); Eso dio una excepción de datos del marco.
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) { }
        }

Simplemente instale 7 zip desde la fuente y pase el parámetro al método.

Gracias. Por favor, dale me gusta a la respuesta.

Vishal Sen
fuente
Esto funcionó para mí en un servicio de Windows con 7za.exe
Marco Duindam
1

Yo uso este codigo

                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();
estilo de vida por átomo
fuente
1

Instale el paquete NuGet llamado SevenZipSharp.Interop

Luego:

SevenZipBase.SetLibraryPath(@".\x86\7z.dll");
var compressor = new SevenZip.SevenZipCompressor();
var filesToCompress = Directory.GetFiles(@"D:\data\");
compressor.CompressFiles(@"C:\archive\abc.7z", filesToCompress);
Fidel
fuente
Intenté agregar un archivo al archivo 7z existente con él y se corrompió el archivo.
Geograph
1

Alguna información de prueba adicional sobre el código de @Orwellophile usando un archivo de texto de 17,9 MB.
El uso de los valores de propiedad en el código de ejemplo "tal cual" tendrá un ENORME impacto negativo en el rendimiento, tarda 14,16 segundos .

Establecer las propiedades de la siguiente manera hace el mismo trabajo en 3.91 segundos (por ejemplo, el archivo tendrá la misma información de contenedor, que es: puede extraer y probar el archivo con 7zip pero no hay información de nombre de archivo)

7zip nativo 2 seg.

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

Hice otra prueba usando 7zip nativo y un archivo de respaldo SQL de 1,2GB (.bak)
7zip (compresión máxima): 1 minuto
LZMA SDK (@Orwellophile con la configuración de propiedad anterior): 12:26 min :-(
Outputfile aproximadamente del mismo tamaño .

Así que supongo que usaré una solución basada en el motor c / c ++, ya sea llamar al ejecutable 7zip desde c # o usar squid-box / SevenZipSharp , que es un envoltorio alrededor del archivo 7zip c / c ++ dll, y parece para ser la bifurcación más nueva de SevenZipSharp. No he probado el contenedor, pero espero que funcione igual que el 7zip nativo. Pero con suerte, también dará la posibilidad de comprimir el flujo, lo que obviamente no puede si llama al exe directamente. De lo contrario, supongo que no hay una gran ventaja sobre llamar al exe. El contenedor tiene algunas dependencias adicionales por lo que no hará que su proyecto publicado sea "más limpio".

Por cierto, parece que el equipo de .Net Core considera implementar LZMA en la clase system.io en .Core ver. 5, ¡eso sería genial!

(Sé que esto es una especie de comentario y no una respuesta, pero para poder proporcionar el fragmento de código, no podría ser un comentario)

MrCalvin
fuente
0

Esta forma más sencilla es trabajar con archivos .zip en lugar de .7z y usar Dot Net Zip

Al girar los comandos 7zip al shell, hay otros problemas como los privilegios de usuario, tuve un problema 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
Brent
fuente
0

SharpCompress es, en mi opinión, una de las bibliotecas de compresión más inteligentes que existen. Es compatible con LZMA (7-zip), es fácil de usar y está en desarrollo activo.

Como ya tiene soporte de transmisión LZMA, en el momento de escribir este artículo, lamentablemente solo admite la lectura de archivos 7-zip. PERO la escritura de archivos está en su lista de tareas pendientes (ver léame). Para futuros lectores: Verifique para obtener el estado actual aquí: https://github.com/adamhathcock/sharpcompress/blob/master/FORMATS.md

Mario Eis
fuente