个性化阅读
专注于IT技术分析

如何在WinForms中使用C#使用SharpZipLib创建和提取zip文件(压缩和解压缩zip)

本文概述

SharpZipLib或以前的NZipLib是完全用C#为.NET平台编写的Zip, GZip, Tar和BZip2库。它实现为程序集(可在GAC中安装), 因此可以轻松地并入其他项目(使用任何.NET语言)。 ziplib的创建者这样说:

我已将zip库移植到C#, 因为我需要gzip / zip压缩, 而且我不想使用libzip.dll或类似的东西。我想要全部使用纯C#。

当然, 在.NET中(至少对于ZIP文件而言)确实有默认工具, 例如System.IO.Compression, 但是它不提供像SharpZipLib这样的成熟库喜欢使用密码来保护文件的所有功能。等。在本文中, 我们将与你分享如何在Visual Studio中安装库以及如何在创建或提取ZIP文件时使用ZIP文件完成典型任务。

1.通过NuGet安装SharpZipLib

首先, 你需要通过nuGet在你的项目中安装该库。打开你的Winforms C#项目, 然后在解决方案资源管理器中打开NuGet程序包管理器:

如何在WinForms中使用C#使用SharpZipLib创建和提取zip文件(压缩和解压缩zip)1

转到浏览选项卡并搜索SharpZipLib:

SharpZipLib Winforms C#

从列表中选择ICSharpCode软件包并安装。软件包安装完成后, 你将可以在课堂上使用它。 ziplib最初是由Mike Krueger开发的, 但是, 许多现有的Java代码在很大程度上帮助加快了该库的创建速度。因此, 荣誉归于他人。ziplib的当前维护者是David Pierson。请通过论坛或Github上的官方存储库与他联系, 以获取有关功能, 错误等的信息。

2.使用库

注意

在本文中, 我们将仅使用ZIP文件, 但是请记住该库可使用TAR, GZip等不同的压缩格式。

基本上, 安装后, 你将需要导入创建ZIP文件所需的命名空间, 即:

using System.IO;
using ICSharpCode.SharpZipLib.Zip;

例子

像在《我们的代码世界》中一样, 一个代码片段意味着一千多个单词, 因此我们将在示例中展示如何在使用C#处理ZIP文件时如何完成大多数的关键任务。

从文件夹内的所有文件创建.zip

以下方法compressDirectory显示如何压缩目录(字符串路径)中的所有文件并将它们附加到单个zip文件中。该方法将文件所在的目录作为第一个参数, 将第二个参数作为将要生成的.zip文件的路径, 最后一个(可选)压缩级别(0-9):

using System.IO;
using ICSharpCode.SharpZipLib.Zip;

/// <summary>
/// Method that compress all the files inside a folder (non-recursive) into a zip file.
/// </summary>
/// <param name="DirectoryPath"></param>
/// <param name="OutputFilePath"></param>
/// <param name="CompressionLevel"></param>
private void compressDirectory(string DirectoryPath, string OutputFilePath, int CompressionLevel = 9)
{
    try
    {
        // Depending on the directory this could be very large and would require more attention
        // in a commercial package.
        string[] filenames = Directory.GetFiles(DirectoryPath);

        // 'using' statements guarantee the stream is closed properly which is a big source
        // of problems otherwise.  Its exception safe as well which is great.
        using (ZipOutputStream OutputStream = new ZipOutputStream(File.Create(OutputFilePath)))
        {

            // Define the compression level
            // 0 - store only to 9 - means best compression
            OutputStream.SetLevel(CompressionLevel);

            byte[] buffer = new byte[4096];

            foreach (string file in filenames)
            {

                // Using GetFileName makes the result compatible with XP
                // as the resulting path is not absolute.
                ZipEntry entry = new ZipEntry(Path.GetFileName(file));

                // Setup the entry data as required.

                // Crc and size are handled by the library for seakable streams
                // so no need to do them here.

                // Could also use the last write time or similar for the file.
                entry.DateTime = DateTime.Now;
                OutputStream.PutNextEntry(entry);

                using (FileStream fs = File.OpenRead(file))
                {

                    // Using a fixed size buffer here makes no noticeable difference for output
                    // but keeps a lid on memory usage.
                    int sourceBytes;

                    do
                    {
                        sourceBytes = fs.Read(buffer, 0, buffer.Length);
                        OutputStream.Write(buffer, 0, sourceBytes);
                    } while (sourceBytes > 0);
                }
            }

            // Finish/Close arent needed strictly as the using statement does this automatically

            // Finish is important to ensure trailing information for a Zip file is appended.  Without this
            // the created file would be invalid.
            OutputStream.Finish();

            // Close is important to wrap things up and unlock the file.
            OutputStream.Close();

            Console.WriteLine("Files successfully compressed");
        }
    }
    catch (Exception ex)
    {
        // No need to rethrow the exception as for our purposes its handled.
        Console.WriteLine("Exception during processing {0}", ex);
    }
}

可以像这样使用:

compressDirectory(
    @"C:\Users\user\Desktop\SomeFolder", @"C:\Users\user\Desktop\SomeFolder\MyOutputFile.zip", 9
);

从文件夹内的所有文件中使用密码创建.zip

如果要为生成的文件定义密码, 则只需使用字符串格式的密码设置ZipOutputStream实例的Password属性:

/// <summary>
/// Method that compress all the files inside a folder (non-recursive) into a zip file.
/// </summary>
/// <param name="DirectoryPath"></param>
/// <param name="OutputFilePath"></param>
/// <param name="CompressionLevel"></param>
private void compressDirectoryWithPassword(string DirectoryPath, string OutputFilePath, string Password = null, int CompressionLevel = 9)
{
    try
    {
        // Depending on the directory this could be very large and would require more attention
        // in a commercial package.
        string[] filenames = Directory.GetFiles(DirectoryPath);

        // 'using' statements guarantee the stream is closed properly which is a big source
        // of problems otherwise.  Its exception safe as well which is great.
        using (ZipOutputStream OutputStream = new ZipOutputStream(File.Create(OutputFilePath)))
        {
            // Define a password for the file (if providen)
            // set its value to null or don't declare it to leave the file
            // without password protection
            OutputStream.Password = Password;

            // Define the compression level
            // 0 - store only to 9 - means best compression
            OutputStream.SetLevel(CompressionLevel);

            byte[] buffer = new byte[4096];

            foreach (string file in filenames)
            {

                // Using GetFileName makes the result compatible with XP
                // as the resulting path is not absolute.
                ZipEntry entry = new ZipEntry(Path.GetFileName(file));

                // Setup the entry data as required.

                // Crc and size are handled by the library for seakable streams
                // so no need to do them here.

                // Could also use the last write time or similar for the file.
                entry.DateTime = DateTime.Now;
                OutputStream.PutNextEntry(entry);

                using (FileStream fs = File.OpenRead(file))
                {

                    // Using a fixed size buffer here makes no noticeable difference for output
                    // but keeps a lid on memory usage.
                    int sourceBytes;

                    do
                    {
                        sourceBytes = fs.Read(buffer, 0, buffer.Length);
                        OutputStream.Write(buffer, 0, sourceBytes);
                    } while (sourceBytes > 0);
                }
            }

            // Finish/Close arent needed strictly as the using statement does this automatically

            // Finish is important to ensure trailing information for a Zip file is appended.  Without this
            // the created file would be invalid.
            OutputStream.Finish();

            // Close is important to wrap things up and unlock the file.
            OutputStream.Close();

            Console.WriteLine("Files successfully compressed");
        }
    }
    catch (Exception ex)
    {
        // No need to rethrow the exception as for our purposes its handled.
        Console.WriteLine("Exception during processing {0}", ex);
    }
}

这种方法可以像这样使用:

// Or to use without password:
// string PasswordForZipFile = null;
string PasswordForZipFile = "ourcodeworld123";

compressDirectoryWithPassword(
    @"C:\Users\user\Desktop\Folders", @"C:\Users\user\Desktop\Folders\DestinationFile.zip", PasswordForZipFile, 9
);

在这种情况下, 密码” ourcodeworld123″将保护对zip文件内容的访问。

将.zip内容提取到文件夹

以下方法提取特定文件夹内的zip文件的内容。第一个参数指定要解压缩的文件的路径, 第二个参数是文件的密码(如果文件没有密码保护, 则可以将其设置为null), 最后一个参数是文件夹的路径, 其中文件内容应提取:

/// <summary>
/// Extracts the content from a .zip file inside an specific folder.
/// </summary>
/// <param name="FileZipPath"></param>
/// <param name="password"></param>
/// <param name="OutputFolder"></param>
public void ExtractZipContent(string FileZipPath, string password, string OutputFolder)
{
    ZipFile file = null;
    try
    {
        FileStream fs = File.OpenRead(FileZipPath);
        file = new ZipFile(fs);

        if (!String.IsNullOrEmpty(password))
        {
            // AES encrypted entries are handled automatically
            file.Password = password;
        }

        foreach (ZipEntry zipEntry in file)
        {
            if (!zipEntry.IsFile)
            {
                // Ignore directories
                continue;           
            }

            String entryFileName = zipEntry.Name;
            // to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
            // Optionally match entrynames against a selection list here to skip as desired.
            // The unpacked length is available in the zipEntry.Size property.

            // 4K is optimum
            byte[] buffer = new byte[4096];     
            Stream zipStream = file.GetInputStream(zipEntry);

            // Manipulate the output filename here as desired.
            String fullZipToPath = Path.Combine(OutputFolder, entryFileName);
            string directoryName = Path.GetDirectoryName(fullZipToPath);

            if (directoryName.Length > 0)
            {
                Directory.CreateDirectory(directoryName);
            }

            // Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
            // of the file, but does not waste memory.
            // The "using" will close the stream even if an exception occurs.
            using (FileStream streamWriter = File.Create(fullZipToPath))
            {
                StreamUtils.Copy(zipStream, streamWriter, buffer);
            }
        }
    }
    finally
    {
        if (file != null)
        {
            file.IsStreamOwner = true; // Makes close also shut the underlying stream
            file.Close(); // Ensure we release resources
        }
    }
}

可以像这样使用:

// If the file doesn't have password
ExtractZipContent(
    @"C:\Users\user\Desktop\SomeFolder\TheFileToDecompress.zip", null, @"C:\Users\user\Desktop\outputfolder"
);

// If the file has password
ExtractZipContent(
    @"C:\Users\user\Desktop\SomeFolder\TheFileToDecompress.zip", "password123", @"C:\Users\user\Desktop\outputfolder"
);

如果你想与SharpZipLib共享另一个有用的片段, 或者你需要与该库的使用相关的内容, 请不要害羞, 并在评论框中分享你的想法。

编码愉快!

赞(0)
未经允许不得转载:srcmini » 如何在WinForms中使用C#使用SharpZipLib创建和提取zip文件(压缩和解压缩zip)

评论 抢沙发

评论前必须登录!