Создайте нормальный zip-файл программно

Я видел много учебных руководств о том, как сжать единственный файл в c#. Но я должен смочь создать нормальный *.zip файл из больше, чем всего одного файла. Есть ли что-нибудь в.NET, которая может сделать это? Что было бы Вы предлагать (обнажающий в памяти, я нахожусь под строгими правилами и не могу пользоваться другими библиотеками),

Спасибо

39
задан 16 March 2010 в 14:07
поделиться

5 ответов

Изменить: если вы используете .Net 4.5 или более позднюю версию, это встроено в структуру

Для более ранних версий или для более поздних версий control вы можете использовать функции оболочки Windows, как описано здесь, в CodeProject Джеральда Гибсона-младшего .

Я скопировал текст статьи ниже в том виде, в каком он был написан (исходная лицензия: общественное достояние )

Сжатие Zip-файлов с помощью Windows Shell API и C

enter image description here

Введение

Это следующая статья к тому, что я писал о распаковке Zip файлов. С помощью этого кода вы можете использовать Windows Shell API на C # для сжатия Zip-файлов и делать это без необходимости показывать окно выполнения копирования, показанное выше. Обычно, когда вы используете Shell API для сжатия Zip-файла, он отображает окно выполнения копирования, даже если вы устанавливаете параметры, чтобы Windows не показывала его.Чтобы обойти это, вы перемещаете код Shell API в отдельный исполняемый файл, а затем запускаете этот исполняемый файл с помощью класса .NET Process, обязательно устанавливая стиль окна процесса на «Скрытый».

Предпосылки

Вам когда-нибудь нужно было сжимать Zip-файлы и нужен был лучший Zip-архив, чем то, что поставляется со многими бесплатными библиотеками сжатия? Т.е. вам нужно было сжать папки и подпапки, а также файлы. Windows Zipping может сжимать не только отдельные файлы. Все, что вам нужно, - это программно заставить Windows автоматически сжимать эти Zip-файлы. Конечно, вы можете потратить 300 долларов на один из коммерческих компонентов Zip, но это трудно превзойти бесплатно, если все, что вам нужно, - это сжать иерархию папок.

Использование кода

Следующий код показывает, как использовать Windows Shell API для сжатия Zip-файла. Сначала вы создаете пустой Zip-файл. Для этого создайте правильно построенный байтовый массив, а затем сохраните этот массив как файл с расширением .zip. Как я узнал, какие байты поместить в массив? Ну, я просто использовал Windows для создания Zip-файла с одним сжатым внутри файлом. Затем я открыл Zip в Windows и удалил сжатый файл. У меня остался пустой почтовый индекс. Затем я открыл пустой Zip-файл в шестнадцатеричном редакторе (Visual Studio), посмотрел на шестнадцатеричные байтовые значения, преобразовал их в десятичные с помощью Windows Calc и скопировал эти десятичные значения в свой код байтового массива. Исходная папка указывает на папку, которую вы хотите сжать. Папка назначения указывает на только что созданный пустой Zip-файл.Этот код как есть сжимает Zip-файл, однако он также отображает окно выполнения копирования. Чтобы этот код работал, вам также нужно будет установить ссылку на библиотеку COM. В окне «Ссылки» перейдите на вкладку COM и выберите библиотеку с надписью «Microsoft Shell Controls and Automation».

//Create an empty zip file
byte[] emptyzip = new byte[]{80,75,5,6,0,0,0,0,0, 
                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

FileStream fs = File.Create(args[1]);
fs.Write(emptyzip, 0, emptyzip.Length);
fs.Flush();
fs.Close();
fs = null;

//Copy a folder and its contents into the newly created zip file
Shell32.ShellClass sc = new Shell32.ShellClass();
Shell32.Folder SrcFlder = sc.NameSpace(args[0]);
Shell32.Folder DestFlder = sc.NameSpace(args[1]); 
Shell32.FolderItems items = SrcFlder.Items();
DestFlder.CopyHere(items, 20);

//Ziping a file using the Windows Shell API 
//creates another thread where the zipping is executed.
//This means that it is possible that this console app 
//would end before the zipping thread 
//starts to execute which would cause the zip to never 
//occur and you will end up with just
//an empty zip file. So wait a second and give 
//the zipping thread time to get started
System.Threading.Thread.Sleep(1000);

Пример решения, включенный в эту статью, показывает, как поместить этот код в консольное приложение, а затем запустить это консольное приложение для сжатия Zip-архива без отображения окна «Ход выполнения копирования».

В приведенном ниже коде показан обработчик события нажатия кнопки, который содержит код, используемый для запуска консольного приложения, чтобы во время сжатия не было пользовательского интерфейса:

private void btnUnzip_Click(object sender, System.EventArgs e)
{
    //Test to see if the user entered a zip file name
    if(txtZipFileName.Text.Trim() == "")
    {
        MessageBox.Show("You must enter what" + 
               " you want the name of the zip file to be");
        //Change the background color to cue the user to what needs fixed
        txtZipFileName.BackColor = Color.Yellow;
        return;
    }
    else
    {
        //Reset the background color
        txtZipFileName.BackColor = Color.White;
    }

    //Launch the zip.exe console app to do the actual zipping
    System.Diagnostics.ProcessStartInfo i =
        new System.Diagnostics.ProcessStartInfo(
        AppDomain.CurrentDomain.BaseDirectory + "zip.exe");
    i.CreateNoWindow = true;
    string args = "";


    if(txtSource.Text.IndexOf(" ") != -1)
    {
        //we got a space in the path so wrap it in double qoutes
        args += "\"" + txtSource.Text + "\"";
    }
    else
    {
        args += txtSource.Text;
    }

    string dest = txtDestination.Text;

    if(dest.EndsWith(@"\") == false)
    {
        dest += @"\";
    }

    //Make sure the zip file name ends with a zip extension
    if(txtZipFileName.Text.ToUpper().EndsWith(".ZIP") == false)
    {
        txtZipFileName.Text += ".zip";
    }

    dest += txtZipFileName.Text;

    if(dest.IndexOf(" ") != -1)
    {
        //we got a space in the path so wrap it in double qoutes
        args += " " + "\"" + dest + "\"";
    }
    else
    {
        args += " " + dest;
    }

    i.Arguments = args;


    //Mark the process window as hidden so 
    //that the progress copy window doesn't show
    i.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;    
    System.Diagnostics.Process p = System.Diagnostics.Process.Start(i);
    p.WaitForExit();
    MessageBox.Show("Complete");
}
20
ответ дан 27 November 2019 в 02:01
поделиться

Вам следует изучить Zip Packages

. Это более структурированная версия обычных ZIP-архивов, требующая наличия некоторых метаданных в корне. Таким образом, другие инструменты ZIP могут открывать пакет, но API Sysytem.IO.Packaging не может открывать все файлы ZIP.

4
ответ дан 27 November 2019 в 02:01
поделиться

Для этого вы можете попробовать SharpZipLib . Это открытый исходный код, платформенно-независимый чистый код C #.

6
ответ дан 27 November 2019 в 02:01
поделиться

Вот несколько ресурсов, которые вы могли бы рассмотреть: Создание Zip-архивов в .NET (без внешней библиотеки, такой как SharpZipLib)

Архивирование ваших потоков с помощью System.IO.Packaging

My Рекомендация и предпочтение - использовать system.io.packacking. Это снижает ваши зависимости (только фреймворк). Сообщение Jgalloway (первая ссылка) представляет собой хороший пример добавления двух файлов в zip-файл. Да, он более подробный, но вы можете легко создать фасад (в какой-то степени это делает его AddFileToZip).

HTH

20
ответ дан 27 November 2019 в 02:01
поделиться

.NET имеет встроенную функциональность для сжатия файлов в пространстве имен System.IO.Compression . Используя это, вам не нужно брать дополнительную библиотеку в качестве зависимости. Эта функция доступна в .NET 2.0.

Вот способ сжатия со страницы MSDN, на которую я ссылался:

    public static void Compress(FileInfo fi)
    {
        // Get the stream of the source file.
        using (FileStream inFile = fi.OpenRead())
        {
            // Prevent compressing hidden and already compressed files.
            if ((File.GetAttributes(fi.FullName) & FileAttributes.Hidden)
                    != FileAttributes.Hidden & fi.Extension != ".gz")
            {
                // Create the compressed file.
                using (FileStream outFile = File.Create(fi.FullName + ".gz"))
                {
                    using (GZipStream Compress = new GZipStream(outFile,
                            CompressionMode.Compress))
                    {
                        // Copy the source file into the compression stream.
                        byte[] buffer = new byte[4096];
                        int numRead;
                        while ((numRead = inFile.Read(buffer, 0, buffer.Length)) != 0)
                        {
                            Compress.Write(buffer, 0, numRead);
                        }
                        Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
                            fi.Name, fi.Length.ToString(), outFile.Length.ToString());
                    }
                }
            }
        }
4
ответ дан 27 November 2019 в 02:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: