Разархивировать файлы программно в .net

Я пытаюсь программно распаковать zipped файл.

Я пробовал использовать класс System.IO.Compression.GZipStream в .NET, но когда мое приложение запускается (на самом деле unit test), я получаю это исключение:

System.IO.InvalidDataException: магическое число в заголовке GZip неверно. Убедитесь, что вы проходите поток GZip.

Теперь я понимаю, что файл .zip не совпадает с файлом .gz, а GZip не совпадает с Zip.

Однако, поскольку я могу извлечь файл вручную, дважды щелкнув по zipped файлу, а затем щелкнув по кнопке "Извлечь все файлы", я думаю, что также должен быть способ сделать это и в коде.

Поэтому я попытался использовать Process.Start() с указанием пути к заархивированному файлу в качестве ввода. Это заставляет мое приложение открывать окно, отображающее содержимое в сжатом файле. Все это прекрасно, но приложение будет установлено на сервере, где нет никого, чтобы нажать кнопку "Извлечь все файлы".

Итак, как мне получить приложение для извлечения файлов в zipped файлах?

Или есть другой способ сделать это? Я предпочитаю делать это в коде, не загружая сторонние библиотеки или приложения; служба безопасности не слишком задумывается об этом...

Ответ 1

Мы успешно использовали SharpZipLib для многих проектов. Я знаю это сторонний инструмент, но исходный код включен и может дать некоторое представление, если вы решили изобрести колесо здесь.

Ответ 2

С .NET 4.5 вы можете распаковать файлы с помощью платформы .NET:

using System;
using System.IO;

namespace ConsoleApplication
{
  class Program
  {
    static void Main(string[] args)
    {
      string startPath = @"c:\example\start";
      string zipPath = @"c:\example\result.zip";
      string extractPath = @"c:\example\extract";

      System.IO.Compression.ZipFile.CreateFromDirectory(startPath, zipPath);
      System.IO.Compression.ZipFile.ExtractToDirectory(zipPath, extractPath);
    }
  }
}

Вышеприведенный код был взят непосредственно из документации Microsoft: http://msdn.microsoft.com/en-us/library/ms404280(v=vs.110).aspx

ZipFile содержится в сборке System.IO.Compression.FileSystem. (Спасибо nateirvin... см. Комментарий ниже)

Ответ 3

Бесплатно и без внешних DLL файлов. Все в одном файле CS. Одна загрузка - это только файл CS, другая загрузка - очень простой пример. Просто попробовал это сегодня, и я не могу поверить, насколько проста была установка. Он работал с первой попытки, никаких ошибок, ничего.

https://github.com/jaime-olivares/zipstorer

Ответ 4

Для .Net 4.5 +

Не всегда желательно записывать несжатый файл на диск. Будучи разработчиком ASP.Net, мне пришлось бы возиться с разрешениями на предоставление прав для моего приложения для записи в файловую систему. Работая с потоками в памяти, я могу обойти все это и напрямую прочитать файлы:

using (ZipArchive archive = new ZipArchive(postedZipStream))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
         var stream = entry.Open();
         //Do awesome stream stuff!!
    }
}

В качестве альтернативы вы все равно можете записать распакованный файл на диск, вызвав ExtractToFile():

using (ZipArchive archive = ZipFile.OpenRead(pathToZip))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        entry.ExtractToFile(Path.Combine(destination, entry.FullName));
    }
} 

Чтобы использовать ZipArchive, вам нужно будет добавить ссылку на System.IO.Compression.FileSystem

Ответ 5

Используйте библиотеку DotNetZip в http://www.codeplex.com/DotNetZip

библиотека классов и набор инструментов для управления zip файлами. Используйте VB, С# или любой язык .NET, чтобы легко создавать, извлекать или обновлять zip файлы...

DotNetZip работает на ПК с полной платформой .NET Framework, а также работает на мобильных устройствах, использующих .NET Compact Framework. Создавайте и читайте zip файлы в VB, С# или любом .NET-языке или в любой среде сценариев...

Если все, что вам нужно, это лучший класс DeflateStream или GZipStream для замены того, который встроен в .NET BCL, DotNetZip тоже. DotNetZip DeflateStream и GZipStream доступны в отдельной сборке на основе .NET-сервера Zlib. Эти потоки поддерживают уровни сжатия и обеспечивают намного лучшую производительность, чем встроенные классы. Существует также ZlibStream для завершения набора (RFC 1950, 1951, 1952)...

Ответ 6

Стандартные zip файлы обычно используют алгоритм дефляции.

Для извлечения файлов без использования сторонних библиотек используйте DeflateStream. Вам потребуется немного больше информации о формате архива zip файла, поскольку Microsoft предоставляет только алгоритм сжатия.

Вы также можете попробовать использовать zipfldr.dll. Это библиотека сжатия Microsoft (сжатые папки из меню "Отправить" ). Кажется, это библиотека com, но она не документирована. Вы можете заставить его работать для вас посредством экспериментов.

Ответ 7

Из здесь:

Сжатые объекты GZipStream, написанные в файл с расширением .gz может декомпрессироваться с использованием многих общих инструменты сжатия; однако этот класс по своей сути не обеспечивает функциональность для добавления файлов или извлечение файлов из архивов .zip.

Ответ 8

Я использую это как для zip, так и для распаковки нескольких файлов. Материал Regex не требуется, но я использую его для изменения штампа даты и удаления нежелательных символов подчеркивания. Я использую пустую строку в строке Compress → zipPath, чтобы при необходимости префикс для всех файлов. Кроме того, я обычно комментирую Compress() или Decompress() на основе того, что я делаю.

using System;
using System.IO.Compression;
using System.IO;
using System.Text.RegularExpressions;

namespace ZipAndUnzip
{
    class Program
    {
        static void Main(string[] args)
        {
            var directoryPath = new DirectoryInfo(@"C:\your_path\");

            Compress(directoryPath);
            Decompress(directoryPath);
        }

        public static void Compress(DirectoryInfo directoryPath)
        {
            foreach (DirectoryInfo directory in directoryPath.GetDirectories())
            {
                var path = directoryPath.FullName;
                var newArchiveName = Regex.Replace(directory.Name, "[0-9]{8}", "20130913");
                newArchiveName = Regex.Replace(newArchiveName, "[_]+", "_");
                string startPath = path + directory.Name;
                string zipPath = path + "" + newArchiveName + ".zip";

                ZipFile.CreateFromDirectory(startPath, zipPath);
            }

        }

        public static void Decompress(DirectoryInfo directoryPath)
        {
            foreach (FileInfo file in directoryPath.GetFiles())
            {
                var path = directoryPath.FullName;
                string zipPath = path + file.Name;
                string extractPath = Regex.Replace(path + file.Name, ".zip", "");

                ZipFile.ExtractToDirectory(zipPath, extractPath);
            }
        }


    }
}

Ответ 9

Вы можете сделать все это в .NET 3.5 с помощью DeflateStream. Недостатком .NET 3.5 является возможность обработки разделов заголовков файлов, которые используются для организации файлов с zip файлами. PKWare опубликовала эту информацию, которую вы можете использовать для обработки zip файла после создания используемых структур. Это не особенно обременительно, и это хорошая практика в создании инструмента без использования стороннего кода.

Это не один ответ, но это вполне выполнимо, если вы готовы и можете сами провести время. Я написал класс, чтобы сделать это через пару часов, и то, что я получил от этого, - это возможность делать zip и распаковывать файлы только с помощью .NET 3.5.

Ответ 10

Я узнал о этом (пакет Unzip на NuGet) сегодня, так как я столкнулся с жесткой ошибкой в ​​DotNetZip, и я понял там на протяжении последних двух лет на DotNetZip не так много работали.

Пакет Unzip является худым, и он выполнял эту работу для меня - у него не было ошибки, которую DotNetZip имел. Кроме того, это был достаточно маленький файл, основанный на Microsoft BCL для фактической декомпрессии. Я мог бы легко внести коррективы, которые мне нужны (чтобы отслеживать прогресс при распаковке). Я рекомендую его.

Ответ 11

Из Embed Ressources:

using (Stream _pluginZipResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(programName + "." + "filename.zip"))
{
    using (ZipArchive zip = new ZipArchive(_pluginZipResourceStream))
    {
        zip.ExtractToDirectory(Application.StartupPath);
    }
}

Ответ 12

До сих пор я использовал cmd-процессы, чтобы извлечь .iso файл, скопировать его во временный путь с сервера и извлечь его на USB-накопителе. Недавно я обнаружил, что это отлично работает с .iso, которые меньше 10 ГБ. Для iso like 29Gb этот метод как-то застрял.

    public void ExtractArchive()
    {
        try
        {

            try
            {
                Directory.Delete(copyISOLocation.OutputPath, true); 
            }
            catch (Exception e) when (e is IOException || e is UnauthorizedAccessException)
            {
            }

            Process cmd = new Process();
            cmd.StartInfo.FileName = "cmd.exe";
            cmd.StartInfo.RedirectStandardInput = true;
            cmd.StartInfo.RedirectStandardOutput = true;
            cmd.StartInfo.CreateNoWindow = true;
            cmd.StartInfo.UseShellExecute = false;
            cmd.StartInfo.WindowStyle = ProcessWindowStyle.Normal;

            //stackoverflow
            cmd.StartInfo.Arguments = "-R";

            cmd.Disposed += (sender, args) => {
                Console.WriteLine("CMD Process disposed");
            };
            cmd.Exited += (sender, args) => {
                Console.WriteLine("CMD Process exited");
            };
            cmd.ErrorDataReceived += (sender, args) => {
                Console.WriteLine("CMD Process error data received");
                Console.WriteLine(args.Data);
            };
            cmd.OutputDataReceived += (sender, args) => {
                Console.WriteLine("CMD Process Output data received");
                Console.WriteLine(args.Data);
            };

            //stackoverflow


            cmd.Start();

            cmd.StandardInput.WriteLine("C:");
            //Console.WriteLine(cmd.StandardOutput.Read());
            cmd.StandardInput.Flush();

            cmd.StandardInput.WriteLine("cd C:\\\"Program Files (x86)\"\\7-Zip\\");
            //Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            cmd.StandardInput.Flush();

            cmd.StandardInput.WriteLine(string.Format("7z.exe x -o{0} {1}", copyISOLocation.OutputPath, copyISOLocation.TempIsoPath));
            //Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            cmd.StandardInput.Flush();
            cmd.StandardInput.Close();
            cmd.WaitForExit();
            Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            Console.WriteLine(cmd.StandardError.ReadToEnd());

Ответ 13

String ZipPath = @"c:\my\data.zip";
String extractPath = @"d:\\myunzips";
ZipFile.ExtractToDirectory(ZipPath, extractPath);

Чтобы использовать класс ZipFile, вы должны добавить ссылку на сборку System.IO.Compression.FileSystem в своем проекте