Как мне создать 7-Zip архивы с.NET?

Как я могу создать 7-Zip архивы из моего консольного приложения C#? Мне нужно иметь возможность извлекать архивы, используя обычную, широко доступную программу 7-Zip.


Вот мои результаты с примерами, предоставленными в качестве ответов на этот вопрос

  • "Обстреливать" 7z.exe - это самый простой и эффективный подход, и я могу подтвердить, что он работает хорошо. Как упоминает workmad3, мне просто нужно гарантировать, что 7z.exe установлен на всех целевых машинах, что я могу гарантировать.
  • 7Zip in memory memory - это сжатие файлов cookie в памяти перед отправкой клиенту; этот метод кажется несколько перспективным. Методы обертки (обертывание LZMA SDK) возвращают тип byte[], Когда я пишу byte[] массив в файл, я не могу извлечь его с помощью 7-Zip (File.7z is not supported archive).
  • 7zSharp Wrapper (находится на CodePlex) - это обертка 7z exe / LZMA SDK. Я ссылался на проект из моего приложения, и он успешно создал несколько архивных файлов, но я не смог извлечь файлы с помощью обычной программы 7-Zip (File.7z is not supported archive).
  • 7Zip SDK или LZMA SDK - я думаю, что я недостаточно умен, чтобы понять, как это использовать (вот почему я разместил здесь)... Любые примеры работающего кода, демонстрирующие создание архива 7zip, который может быть извлечен обычная программа 7zip?
  • Интерфейс CodeProject C# (.NET) для библиотек DLL 7-Zip - поддерживает только извлечение из архивов 7zip... Мне нужно их создавать!
  • SharpZipLib - Согласно их часто задаваемым вопросам, SharpZipLib не поддерживает 7zip.

12 ответов

Решение

Если вы можете гарантировать, что приложение 7-zip будет установлено (и в пути) на всех целевых машинах, вы можете разгрузиться, вызвав приложение командной строки 7z. Не самое элегантное решение, но это наименьшая работа.

Пример cookie-файла 7ggip в EggCafe Это пример (cookie-файл) с DLL-библиотекой 7Zip.

CodePlex Wrapper Это проект с открытым исходным кодом, который деформирует функцию архивирования 7z.

7Zip SDK Официальный SDK для 7zip (C, C++, C#, Java) <--- Мое предложение

.Net zip библиотека от SharpDevelop.net

Пример CodeProject с 7zip

SharpZipLib Много молний

SevenZipSharp - другое решение. Создает 7-почтовый архив...

Вот полный рабочий пример использования SevenZip SDK в C#.

Он будет записывать и читать стандартные файлы 7zip, созданные в приложении Windows 7zip.

PS. Предыдущий пример никогда не собирался распаковывать, потому что он никогда не записывал необходимую информацию о свойствах в начало файла.

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

Я использовал SDK.

например:

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

Просто установите 7 zip из исходного кода и передайте параметр методу.

Благодарю. Пожалуйста, как ответ.

Некоторая дополнительная информация о тесте для кода @Orwellophile с использованием текстового файла размером 17,9 МБ.
Использование значений свойств в примере кода "как есть" окажет ОГРОМНОЕ негативное влияние на производительность, это займет 14,16 с.

Установка свойств для следующего делает ту же работу за 3,91 секунды (то есть архив будет иметь ту же информацию о контейнере, что и вы: вы можете извлечь и протестировать архив с 7zip, но нет информации об имени файла)

Родной 7zip 2 сек.

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

Я сделал еще один тест, используя родной 7zip и файл резервной копии SQL объемом 1,2 ГБ (.bak)
7zip (максимальное сжатие): 1 минута
LZMA SDK (@Orwellophile с указанными выше настройками свойств): 12:26 мин:-(
Выходной файл примерно одинакового размера.

Так что, я думаю, я сам буду использовать решение, основанное на движке c/ C++, то есть либо вызову исполняемого файла 7zip из C#, либо использование https://github.com/squid-box/SevenZipSharp, который является оболочкой для файла 7zip c/ C++ dll, и кажется, быть новейшей вилкой SevenZipSharp. Не проверял упаковщик, но я надеюсь, что он работает так же, как родной 7zip. Но, надеюсь, это даст возможность сжимать поток также, что вы, очевидно, не можете, если вы вызываете exe напрямую. В противном случае я думаю, что нет никакого преимущества перед вызовом exe. Оболочка имеет некоторые дополнительные зависимости, поэтому она не сделает ваш опубликованный проект "чище".

Кстати, кажется, что команда.Net Core рассматривает возможность реализации LZMA в классе system.io в.Core ver. 5, это было бы здорово!

(Я знаю, что это своего рода комментарий, а не ответ, но чтобы предоставить фрагмент кода, он не может быть комментарием)

Я использую этот код

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

Установите пакет NuGet под названием SevenZipSharp.Interop

Затем:

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

Это самый простой способ - работать с файлами.zip вместо.7z и использовать Dot Net Zip.

При выделении команд 7zip для оболочки возникают другие проблемы, такие как пользовательские привилегии, у меня была проблема с 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

SharpCompress, на мой взгляд, одна из самых умных библиотек сжатия. Он поддерживает LZMA (7-zip), прост в использовании и активно развивается.

Поскольку он уже поддерживает потоковую передачу LZMA, на момент написания он, к сожалению, поддерживает только чтение 7-zip-архива. НО запись архива находится в их списке задач (см. Readme). Для будущих читателей: проверьте, чтобы получить текущий статус здесь: https://github.com/adamhathcock/sharpcompress/blob/master/FORMATS.md

Вот код для создания и извлечения 7zip (на основе LZMA SDK - C#)

Примечание. Архивы 7z, созданные с использованием того же кода, можно разархивировать. Поскольку код использует управляемую LZMA с использованием более ранней версии LZMA SDK

Другие вопросы по тегам