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


102

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


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

  • «Обстрел» до 7z.exe - это самый простой и эффективный подход, и я могу подтвердить, что он работает нормально . Как упоминает workmad3 , мне просто нужно гарантировать, что 7z.exe установлен на всех целевых машинах, что я могу гарантировать.
  • 7Zip сжатие в памяти - это относится к сжатию файлов 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 Archive - поддерживает извлечение только из архивов 7zip ... Мне нужно их создать!
  • SharpZipLib - Согласно их FAQ , SharpZipLib не поддерживает 7zip.

32
Не пишите это из Google, когда все ссылки из моего поста ниже. Не очень уважительные к людям, которые нашли время, чтобы найти вам какое-то решение.
Патрик Дежарден,

3
Я знаю, что этот пост старый, но сегодня в моем исследовании я видел проект под названием SevenZipSharp. sevenzipsharp.codeplex.com
Тиммерц

12
Просто предупреждение для будущих читателей. SevenZipSharp кажется заброшенным программным обеспечением. На сегодняшний день последний стабильный выпуск (0.64) был выпущен еще в августе 2010 года с некоторыми неприятными проблемами многопоточности (согласно отчетам об ошибках). С тех пор было опубликовано лишь несколько коммитов исходного кода .
Anttu

Ответы:


28

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


7
На самом деле мы поставляем утилиту командной строки 7z с нашими двоичными файлами и оболочкой для нее. У нас действительно хорошо работает.
Дэвид Мохундро,

81

Пример файла cookie EggCafe 7Zip Это пример (сжатый файл cookie) с DLL 7Zip.

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

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

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

Пример CodeProject с 7zip

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


Готово, и я добавил полезный проект с открытым исходным кодом.
Патрик Дежарден,

1
РЖУНИМАГУ? Измените cookie на строку ... файл или что-то еще ... lol?
Патрик Дежарден,

1
Нет, я просто хочу посмотреть, придумал ли кто-нибудь рабочий пример ... Спасибо за ваше исследование, но ни одна из предоставленных вами ссылок не смогла привести меня к чему-то, что работает.
Seibar,

2
Я должен согласиться с тем, что ни у кого нет кода, который можно было бы скопировать и вставить. SDK - это тот самый ответ, но для того, чтобы что-то работало, нужно время и усилия. Я понимаю, что вы не хотите этого делать. Хорошего дня.
Патрик Дежарден,

3
В любом случае, я предлагаю удалить ссылки SharpDevelop / SharpZipLib, поскольку оба относятся к одному и тому же и не поддерживают 7-Zip. Сейбар явно просил 7z. Я также ищу решения 7z, потому что ShaprZipLib не работал с архивом и нашел эту ветку. ShaprZipLib - обманчивая подсказка!
Onsokumaru

25

SevenZipSharp - еще одно решение. Создает 7-zip архивы ...


7
Этот пост мархора на самом деле от создателя проекта SevenZipSharp. SevenZipSharp обеспечивает программный доступ к dll 7Zip, что делает ее очень полнофункциональной. Я нашел LZMA SDK низкоуровневым и трудным для понимания. SevenZipSharp, напротив, хорошо документирован, прост в использовании и имеет множество примеров использования в своем тестовом проекте. Используя примеры, я мог быстро сжимать и распаковывать файлы или память.
Джон Виггер,

4
SevenZipSharp, похоже, заброшен. См. Мой предыдущий комментарий в вопросе.
Anttu

SevenZipSharp работает медленно. На данный момент наиболее рекомендуемым решением является использование Process.Start ("7z.exe ......)
klm_ 01

25

Вот полный рабочий пример с использованием 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");
        }
    }
}

15
Обратите внимание, что это чистое сжатие / декомпрессия LZMA. Формат файла 7zip - это уровень выше этого, который позволяет упаковывать несколько файлов вместе с именами файлов / путями и другими метданными файлов.
redcalx

1
@redcalx правильный. Кто-нибудь знает, как обработать верхний, 7zip слой? Ссылка на другой пост SO была бы замечательной :)
Christopher J Smith

8

Я использовал 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();
      }
   }
}

7
А как распаковать файл будешь? Я попытался сделать то же самое, используя SevenZip.Compression.LZMA.Decoder и вызвав его с помощью Code (stream1, stream2, -1, -1, null); Это дало исключение данных из фреймворка.
Карстен

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

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

Спасибо. Пожалуйста, понравился ответ.


Это сработало для меня в службе Windows с 7za.exe
Марко Дуиндам

1

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

                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

Установите пакет 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);

Я попытался добавить с его помощью файл в существующий 7z-архив и получил испорченный архив.
География

1

Некоторая дополнительная информация о тестировании кода @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 #, либо использую squid-box / SevenZipSharp , который является оболочкой для файла dll 7zip c / c ++, и кажется быть новейшим форком SevenZipSharp. Обертку не тестировал, но надеюсь, что она работает так же, как родной 7zip. Но, надеюсь, это даст возможность сжимать поток, чего вы, очевидно, не сможете, если вызовете exe напрямую. В противном случае, я думаю, нет большого преимущества перед вызовом exe. Оболочка имеет некоторые дополнительные зависимости, поэтому она не сделает ваш опубликованный проект «чище».

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

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


0

Самый простой способ - работать с файлами .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

0

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.