Como faço para criar arquivos 7-Zip com .NET?

101

Como posso criar arquivos 7-Zip do meu aplicativo de console C #? Preciso extrair os arquivos usando o programa 7-Zip comum e amplamente disponível .


Aqui estão meus resultados com os exemplos fornecidos como respostas a esta pergunta

  • "Descarte" para 7z.exe - esta é a abordagem mais simples e eficaz, e posso confirmar que funciona bem . Como o workmad3 menciona , só preciso garantir que o 7z.exe esteja instalado em todas as máquinas de destino, o que posso garantir.
  • 7Zip na compactação de memória - refere-se à compactação de cookies "na memória" antes de enviá-los ao cliente; este método parece um tanto promissor. O tipo de retorno dos métodos de wrapper (envolvendo o SDK LZMA ) byte[]. Quando escrevo o byte[]array em um arquivo, não consigo extraí-lo usando 7-Zip ( File.7z is not supported archive).
  • Wrapper 7zSharp (encontrado no CodePlex) - envolve o 7z exe / LZMA SDK . Referenciei o projeto do meu aplicativo e ele criou alguns arquivos compactados com sucesso, mas não consegui extrair os arquivos usando o programa 7-Zip normal ( File.7z is not supported archive).
  • 7Zip SDK também conhecido como LZMA SDK - acho que não sou inteligente o suficiente para descobrir como usar isso (é por isso que postei aqui) ... Qualquer exemplo de código de trabalho que demonstre a criação de um arquivo 7zip que pode ser extraído pelo programa 7zip regular?
  • Interface CodeProject C # (.NET) para 7-Zip Archive DLLs - suporta apenas extração de arquivos 7zip ... Eu preciso criá-los!
  • SharpZipLib - De acordo com seu FAQ , SharpZipLib não oferece suporte a 7zip.
Seibar
fonte
32
Não escreva é do Google quando todos os links são da minha postagem abaixo. Não é muito respeitoso para as pessoas que se deram ao trabalho de buscar para vocês algumas soluções.
Patrick Desjardins,
3
Eu sei que este post é antigo, mas eu vi um projeto chamado SevenZipSharp na minha pesquisa hoje. sevenzipsharp.codeplex.com
Timmerz
12
Apenas uma palavra de advertência para futuros leitores. O SevenZipSharp parece ser abandonware. A partir de hoje, a última versão estável (0,64) foi lançada em agosto de 2010 com alguns problemas de multithreading desagradáveis ​​(de acordo com os relatórios de bug). Apenas alguns commits de código-fonte foram postados desde então.
Anttu de

Respostas:

28

Se você pode garantir que o aplicativo 7-zip será instalado (e no caminho) em todas as máquinas de destino, você pode descarregar chamando o aplicativo de linha de comando 7z. Não é a solução mais elegante, mas dá menos trabalho.

workmad3
fonte
7
Na verdade, enviamos o utilitário de linha de comando 7z com nossos binários e executamos a shell. Funciona muito bem para nós.
David Mohundro,
79

Exemplo de cookie EggCafe 7Zip Este é um exemplo (zipping cookie) com a DLL de 7Zip.

CodePlex Wrapper Este é um projeto de código aberto que distorce a função de compactação de 7z.

7Zip SDK O SDK oficial para 7zip (C, C ++, C #, Java) <--- Minha sugestão

Biblioteca .Net zip por SharpDevelop.net

Exemplo de CodeProject com 7zip

SharpZipLib Muitos fechamentos

Patrick Desjardins
fonte
Feito e eu adicionei um projeto de código aberto útil também.
Patrick Desjardins,
1
RI MUITO? Mude o cookie por uma string ... um arquivo ou o que for ... lol?
Patrick Desjardins,
1
Não, só quero ver se alguém encontrou um exemplo funcional ... Obrigado por sua pesquisa, mas nenhum dos links que você forneceu foi capaz de me levar a algo que funcione.
Seibar,
2
Tenho que concordar que nenhum tem um código que você possa copiar e colar. O SDK é quem tem todas as respostas, mas leva algum tempo e esforço para ter algo que funcione. Eu posso entender que você não quer fazer isso. Tenha um bom dia.
Patrick Desjardins,
3
De qualquer forma, sugiro remover as referências SharpDevelop / SharpZipLib, pois ambas se referem ao mesmo e não suportam 7-Zip. Seibar pediu explicitamente 7z. Também estou procurando soluções 7z porque ShaprZipLib não funcionou com o arquivo e encontrou este tópico. ShaprZipLib é uma dica enganosa!
Onsokumaru
25

SevenZipSharp é outra solução. Cria arquivos 7-zip ...

markhor
fonte
7
Esta postagem de markhor é, na verdade, do criador do projeto SevenZipSharp. SevenZipSharp permite acesso programático ao dll 7Zip, tornando-o muito completo. Achei o SDK do LZMA de baixo nível e difícil de entender. SevenZipSharp, por outro lado, é bem documentado, fácil de usar e tem muitos exemplos de uso em seu projeto de teste. Usando os exemplos, eu poderia compactar e descompactar rapidamente usando arquivo ou memória.
John Wigger
4
SevenZipSharp parece estar abandonado. Veja meu comentário anterior na pergunta.
Anttu
SevenZipSharp é lento. No momento, a solução mais recomendada é usar Process.Start ("7z.exe ......)
klm_ 01 de
24

Aqui está um exemplo de trabalho completo usando o SDK SevenZip em C #.

Ele gravará e lerá arquivos 7zip padrão criados pelo aplicativo Windows 7zip.

PS. O exemplo anterior nunca iria descompactar porque nunca gravou as informações de propriedade necessárias no início do arquivo.

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
fonte
15
Observe que esta é a compressão / descompressão LZMA pura. O formato de arquivo 7zip é uma camada acima que permite o empacotamento de vários arquivos junto com os nomes / caminhos dos arquivos e outros metadados do arquivo.
redcalx
1
@redcalx está correto. Alguém tem ideia de como processar a camada 7zip superior? Seria ótimo fazer referência a outro post do SO :)
Christopher J Smith
8

Eu usei o sdk.

por exemplo:

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
fonte
7
E como você vai descompactar o arquivo? Tentei fazer o mesmo usando o SevenZip.Compression.LZMA.Decoder e chamando-o com Code (stream1, stream2, -1, -1, null); Isso gerou uma exceção de dados da estrutura.
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 instalar o 7 zip da fonte e passar o parâmetro para o método.

Obrigado. Por favor, goste da resposta.

Vishal Sen
fonte
Isso funcionou para mim em um serviço do Windows com 7za.exe
Marco Duindam
1

Eu uso este código

                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
fonte
1

Instale o pacote NuGet chamado SevenZipSharp.Interop

Então:

SevenZipBase.SetLibraryPath(@".\x86\7z.dll");
var compressor = new SevenZip.SevenZipCompressor();
var filesToCompress = Directory.GetFiles(@"D:\data\");
compressor.CompressFiles(@"C:\archive\abc.7z", filesToCompress);
Fidel
fonte
Tentei adicionar o arquivo ao arquivo 7z existente com ele e o arquivo foi corrompido.
Geograph de
1

Algumas informações adicionais de teste sobre o código @Orwellophile usando um arquivo de texto de 17,9 MB.
Usar os valores da propriedade no exemplo de código "como está" terá um impacto negativo ENORME no desempenho, leva 14,16 segundos .

Definir as propriedades para o seguinte faz o mesmo trabalho em 3,91 segundos (isto é, o arquivo terá as mesmas informações do contêiner, que é: você pode extrair e testar o arquivo com 7zip, mas não há informações do nome do arquivo)

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

Fiz outro teste usando 7zip nativo e um arquivo de backup SQL de 1,2 GB (.bak)
7zip (compactação máxima): SDK LZMA de 1 minuto
(@Orwellophile com configuração de propriedade acima): 12:26 min :-(
Arquivo de saída aproximadamente do mesmo tamanho .

Então, acho que vou usar uma solução baseada no motor c / c ++, ia chamar o executável 7zip de c # ou usar squid-box / SevenZipSharp , que é um wrapper em torno do arquivo 7zip c / c ++ dll, e parece para ser o mais novo fork do SevenZipSharp. Ainda não testei o wrapper, mas espero que funcione exatamente como o 7zip nativo. Mas, com sorte, isso dará a possibilidade de compactar stream também, o que você obviamente não poderá se chamar o exe diretamente. Caso contrário, acho que não há nenhuma vantagem sobre ligar para o exe. O wrapper tem algumas dependências adicionais, portanto, não tornará seu projeto publicado "mais limpo".

A propósito, parece que a equipe do .Net Core considera a implementação do LZMA na classe system.io na versão .Core. 5, isso seria ótimo!

(Eu sei que isso é uma espécie de comentário e não uma resposta, mas para ser capaz de fornecer o snippet de código, não poderia ser um comentário)

MrCalvin
fonte
0

A maneira mais fácil é trabalhar com arquivos .zip em vez de .7z e usar Dot Net Zip

Ao girar os comandos 7zip para o shell, existem outros problemas, como privilégios de usuário, tive problemas com o 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
fonte
0

SharpCompress é, na minha opinião, uma das bibliotecas de compressão mais inteligentes que existem. Suporta LZMA (7-zip), é fácil de usar e está em desenvolvimento ativo.

Como já tem suporte para streaming LZMA, no momento em que este artigo foi escrito, infelizmente, só suportava leitura de arquivo 7-zip. MAS a escrita de arquivo está em sua lista de tarefas (consulte o leia-me). Para leitores futuros: verifique para obter o status atual aqui: https://github.com/adamhathcock/sharpcompress/blob/master/FORMATS.md

Mario Eis
fonte