Як створити 7-Zip архіви за допомогою .NET?


101

Як я можу створити 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 aka 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 року з деякими неприємними проблемами з багатопотоковістю (згідно з повідомленнями про помилки). З тих пір було опубліковано лише декілька комісій з вихідного коду .
Антту

Відповіді:


28

Якщо ви можете гарантувати, що додаток на 7 zip буде встановлено (і на шляху) на всіх цільових машинах, ви можете вивантажитись, зателефонувавши в додаток командного рядка 7z. Не найелегантніше рішення, але це найменша робота.


7
Ми фактично доставляємо утиліту командного рядка 7z разом з нашими бінарними файлами та надаємо їй оболонку. Діє дуже добре для нас.
Девід Мохундро

79

Приклад файлу cookie EggCafe 7Zip Це приклад (блискавичний файл cookie) з DLL 7Zip.

CodePlex Wrapper - це проект з відкритим кодом, який виконує функцію блискавки 7z.

7Zip SDK Офіційний SDK для 7zip (C, C ++, C #, Java) <--- Моя пропозиція

.Net поштова бібліотека від SharpDevelop.net

Приклад CodeProject із 7zip

SharpZipLib Багато блискавок


Ми з вами додали і проект з відкритим кодом.
Патрік Дежардінс

1
ЛОЛ? Змініть файл cookie рядком ... файлом чи іншим ... lol?
Патрік Дежардінс

1
Ні, я просто хочу перевірити, чи хтось придумав робочий приклад ... Дякую за ваше дослідження, але жодне із наданих вами посилань не змогло привести мене до чогось, що працює.
Сейбар

2
Я повинен погодитися, що жоден не має коду, який можна скопіювати та вставити. SDK - це відповідь на всі відповіді, але потрібен певний час і зусилля, щоб щось працювало. Я можу зрозуміти, що ти не хочеш цього робити. Гарного дня.
Патрік Дежардінс

3
У будь-якому випадку, я пропоную видалити посилання SharpDevelop / SharpZipLib, оскільки обидва посилаються на одне і те ж і не підтримують 7-Zip. Сейбар запитав явно за 7z. Я також шукаю рішення 7z, тому що ShaprZipLib не працював з архівом і знайшов цю тему. ShaprZipLib - хибний підказ!
Онсокумару

25

SevenZipSharp - ще одне рішення. Створює 7-zip архіви ...


7
Це повідомлення від Markhor насправді є автором проекту SevenZipSharp. SevenZipSharp дозволяє програмно отримати доступ до dll 7Zip, що робить його дуже повнофункціональним. Я виявив, що LKMA SDK є низькорівневим і важким для розуміння. Навпаки, SevenZipSharp добре документований, простий у використанні та має багато зразкових звичаїв у своєму тестовому проекті. Використовуючи приклади, я міг швидко стискати та розпаковувати за допомогою файлу чи пам'яті.
Джон Віггер

4
Здається, що SevenZipSharp покинуто. Дивіться мій попередній коментар у питанні.
Антту

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

24

Ось повний робочий приклад із використанням SDK SevenZip в 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 була б чудовою :)
Крістофер Дж Сміт

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 і викликаючи його за допомогою коду (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
Marco Duindam,

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 та 1,2-базірний файл резервного копіювання SQL (.bak)
7zip (максимальна компресія): 1 хвилина
SDK LZMA (@Orwellophile з вищевказаною настройкою властивості): 12:26 хв :-(
Outputfile приблизно однакового розміру .

Тож я думаю, що я сам буду використовувати рішення, засноване на двигуні 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 архіву. АЛЕ написання архіву є у їхньому списку todo (див. Readme). Для майбутніх читачів: Перевірте, щоб отримати поточний статус тут: https://github.com/adamhathcock/sharpcompress/blob/master/FORMATS.md

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.