【随笔系列】C#使用第三方SharpZipLib进行压缩、解压文件

近在做项目时用到了文件的批量压缩下载,使用了第三方的SharpZipLib包,后来想到了单个文件的压缩与解压,可能以后会用到相关技术,所以自己熟悉了一下并且借鉴了一些网上的相关代码,自己整理一下,这里我用到的是SharpZipLib 1.0.0版本,这里我新建一个控制台项目来展示。

 

一:创建项目并安装所需DLL

1、新建控制台项目ConsoleCompressApp

2、通过VisualStudio菜单中工具->NuGet包管理器->程序包管理控制台安装SharpZipLib包

命令是Install-Package SharpZipLib,如下图显示,已安装完成。

也可以通过鼠标选中项目然后右键弹出的菜单中选择管理NuGet程序包

选择第一个SharpZipLib包选择安装即可。

 

二:创建日志记录帮助类LogHelper

 1 using System;
 2 using System.IO;
 3 
 4 namespace ConsoleCompressApp
 5 {
 6     public class LogHelper
 7     {
 8         private static readonly object __lockObject = new object();
 9         public static void Write(string message, string txtFileName = "")
10         {
11             try
12             {
13                 if (string.IsNullOrWhiteSpace(txtFileName))
14                 {
15                     txtFileName = AppDomain.CurrentDomain.BaseDirectory + Path.DirectorySeparatorChar + "log.txt";
16                 }
17                 FileStream fs = null;
18                 if (File.Exists(txtFileName))
19                 {
20                     fs = new FileStream(txtFileName, FileMode.Append);
21                 }
22                 else
23                 {
24                     fs = new FileStream(txtFileName, FileMode.Create);
25                 }
26                 lock (__lockObject)
27                 {
28                     if (File.Exists(txtFileName) == false)
29                     {
30                         File.Create(txtFileName);
31                     }
32                     using (StreamWriter sw = new StreamWriter(fs))
33                     {
34                         sw.Write("{0}:{1}", DateTime.Now.ToString("yyyy年MM月dd日 HH:mm:ss"), message + sw.NewLine);
35                     }
36                 }
37 
38             }
39             catch (Exception)
40             {
41                 throw;
42             }
43         }
44     }
45 }

 

三:创建压缩文件的帮助类SharpZipLibHelper

1、新建SharpZipLibHelper帮助类,并引用如下命名空间

 1 using System;
 2 using System.IO;
 3 using ICSharpCode.SharpZipLib.Checksum;
 4 using ICSharpCode.SharpZipLib.Zip;
 5 
 6 namespace ConsoleCompressApp
 7 {
 8     public class SharpZipLibHelper
 9     {
10 
11     }
12 }

2、添加压缩单个文件的静态方法

 1         /// <summary>
 2         /// 单个文件进行压缩
 3         /// </summary>
 4         /// <param name="fileName">待压缩的文件(绝对路径)</param>
 5         /// <param name="compressedFilePath">压缩后文件路径(绝对路径)</param>
 6         /// <param name="aliasFileName">压缩文件的名称(别名)</param>
 7         /// <param name="compressionLevel">压缩级别0-9,默认为5</param>
 8         /// <param name="blockSize">缓存大小,每次写入文件大小,默认为2048字节</param>
 9         /// <param name="isEncrypt">是否加密,默认加密</param>
10         /// <param name="encryptPassword">加密的密码(为空的时候,不加密)</param>
11         public static void CompressFile(string fileName, string compressedFilePath, string aliasFileName = "", int compressionLevel = 5,
12             int blockSize = 2048, bool isEncrypt = true, string encryptPassword = "")
13         {
14             if (File.Exists(fileName) == false) throw new FileNotFoundException("未能找到当前文件!", fileName);
15             try
16             {
17                 string zipFileName = null;
18                 ///获取待压缩文件名称(带后缀名)
19                 string name = new FileInfo(fileName).Name;
20                 zipFileName = compressedFilePath + Path.DirectorySeparatorChar +
21                     (string.IsNullOrWhiteSpace(aliasFileName) ? name.Substring(0, name.LastIndexOf(".")) : aliasFileName) + ".zip";
22                 ///使用using语句,资源使用完毕,自动释放(类需继承IDispose接口)
23                 using (FileStream fs = File.Create(zipFileName))
24                 {
25                     using (ZipOutputStream outStream = new ZipOutputStream(fs))
26                     {
27                         using (FileStream inStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
28                         {
29                             ///zip文档的一个条目
30                             ZipEntry entry = new ZipEntry(name);
31                             ///压缩加密
32                             if (isEncrypt)
33                             {
34                                 outStream.Password = encryptPassword;
35                             }
36                             ///开始一个新的zip条目
37                             outStream.PutNextEntry(entry);
38                             ///设置压缩级别
39                             outStream.SetLevel(compressionLevel);
40                             ///缓冲区对象
41                             byte[] buffer = new byte[blockSize];
42                             ///读入缓冲区的总字节数,执行到最后读取为0时,则读取完毕
43                             int sizeRead = 0;
44                             do
45                             {
46                                 ///从流中读取字节,将该数据写入缓冲区
47                                 sizeRead = inStream.Read(buffer, 0, buffer.Length);
48                                 ///将给定的缓冲区的数据写入当前zip文档条目
49                                 outStream.Write(buffer, 0, sizeRead);
50                             }
51                             while (sizeRead > 0);
52                         }
53                         outStream.Finish();
54                     }
55                 }
56             }
57             catch (System.Exception ex)
58             {
59                 LogHelper.Write(ex.ToString());
60             }
61         }

3、添加压缩文件目录的静态方法  

  1         /// <summary>
  2         /// 压缩文件夹
  3         /// </summary>
  4         /// <param name="directory">待压缩文件夹(绝对路径)</param>
  5         /// <param name="compressedDirectory">压缩后的文件夹(绝对路径)</param>
  6         /// <param name="aliasFileName">压缩文件的名称(别名)</param>
  7         /// <param name="isEncrypt">是否加密,默认加密</param>
  8         /// <param name="encryptPassword">加密的密码(为空不进行加密)</param>
  9         public static void CompressDirectory(string directory, string compressedDirectory, string aliasFileName, bool isEncrypt,
 10             string encryptPassword = "")
 11         {
 12             if (Directory.Exists(directory) == false) throw new DirectoryNotFoundException("未能找到当前路径!");
 13             try
 14             {
 15                 string zipFileName = null;
 16                 ///获取待压缩文件名称
 17                 string name = new DirectoryInfo(directory).Name;
 18                 zipFileName = compressedDirectory + Path.DirectorySeparatorChar +
 19                     (string.IsNullOrWhiteSpace(aliasFileName) ? name : aliasFileName) + ".zip";
 20 
 21                 ///使用using语句,资源使用完毕,自动释放(类需继承IDispose接口)
 22                 using (FileStream fs = File.Create(zipFileName))
 23                 {
 24                     using (ZipOutputStream outStream = new ZipOutputStream(fs))
 25                     {
 26                         if (isEncrypt)
 27                         {
 28                             ///压缩文件加密
 29                             outStream.Password = encryptPassword;
 30                         }
 31                         CompressTraversal(directory, outStream, "");
 32                         outStream.Finish();
 33                     }
 34                 }
 35             }
 36             catch (System.Exception ex)
 37             {
 38                 LogHelper.Write(ex.ToString());
 39             }
 40         }
 41 
 42         /// <summary>
 43         /// 压缩文件夹,并返回压缩后的文件数据流
 44         /// </summary>
 45         /// <param name="directory">待压缩文件夹(绝对路径)</param> 
 46         /// <param name="isEncrypt">是否加密,默认加密</param>
 47         /// <param name="encryptPassword">加密的密码(为空不进行加密)</param>
 48         public static byte[] CompressDirectoryBytes(string directory, bool isEncrypt, string encryptPassword = "")
 49         {
 50             if (Directory.Exists(directory) == false) throw new DirectoryNotFoundException("未能找到当前路径!");
 51             try
 52             { 
 53                 ///获取待压缩文件名称
 54                 string name = new DirectoryInfo(directory).Name;
 55 
 56                 byte[] buffer = null;
 57 
 58                 MemoryStream ms = new MemoryStream();
 59                 ZipOutputStream outStream = new ZipOutputStream(ms);
 60                 if (isEncrypt)
 61                 {
 62                     ///压缩文件加密
 63                     outStream.Password = encryptPassword;
 64                 }
 65                 CompressTraversal(directory, outStream, "");
 66                 outStream.Finish();
 67 
 68                 buffer = new byte[ms.Length];
 69                 ms.Seek(0, SeekOrigin.Begin);
 70                 ms.Read(buffer, 0, (int)ms.Length);
 71                 return buffer;
 72             }
 73             catch (System.Exception ex)
 74             { 
 75                 LogHelper.Write(ex.ToString());
 76                 return null;
 77             }
 78         }
 79 
 80         /// <summary>
 81         /// 递归遍历目录
 82         /// </summary>
 83         private static void CompressTraversal(string directory, ZipOutputStream outStream, string parentDirectory)
 84         {
 85             ///判断路径最后一个字符是否为当前系统的DirectorySeparatorChar
 86             if (directory[directory.Length - 1] != Path.DirectorySeparatorChar)
 87             {
 88                 directory += Path.DirectorySeparatorChar;
 89             }
 90             Crc32 crc = new Crc32();
 91             var fileOrDirectory = Directory.GetFileSystemEntries(directory);
 92             ///遍历文件与目录
 93             foreach (var item in fileOrDirectory)
 94             {
 95                 ///判断是否为目录
 96                 if (Directory.Exists(item))
 97                 {
 98                     CompressTraversal(item, outStream, (parentDirectory + item.Substring(item.LastIndexOf(Path.DirectorySeparatorChar) + 1) + Path.DirectorySeparatorChar));
 99                 }
100                 ///压缩文件
101                 else
102                 {
103                     using (FileStream inStream = File.OpenRead(item))
104                     {
105                         ///缓存区对象
106                         byte[] buffer = new byte[inStream.Length];
107                         ///将流重置
108                         inStream.Seek(0, SeekOrigin.Begin);
109                         ///从文件流中读取字节,将该数据写入缓存区
110                         inStream.Read(buffer, 0, (int)inStream.Length);
111                         ///获取该文件名称(附带文件目录结构,例如git\\git.exe)
112                         string fileName = parentDirectory + item.Substring(item.LastIndexOf(Path.DirectorySeparatorChar) + 1);
113                         ///创建zip条目
114                         ZipEntry entry = new ZipEntry(fileName);
115                         entry.DateTime = DateTime.Now;
116                         entry.Size = inStream.Length;
117 
118                         crc.Reset();
119                         crc.Update(buffer);
120 
121                         entry.Crc = crc.Value;
122 
123                         outStream.PutNextEntry(entry);
124                         ///将缓存区对象数据写入流中
125                         outStream.Write(buffer, 0, buffer.Length);
126                         ///注意:一定要关闭当前条目,否则压缩包数据会丢失
127                         outStream.CloseEntry();
128                     }
129                 }
130             }
131         }

4、最后添加解压的静态方法

 1         /// <summary>
 2         /// 解压缩
 3         /// </summary>
 4         /// <param name="compressedFile">压缩文件(绝对路径)</param>
 5         /// <param name="directory">目标路径(绝对路径)</param>
 6         /// <param name="encryptPassword">加密密码</param>
 7         /// <param name="overWrite">是否覆盖</param>
 8         /// <param name="blockSize">缓存大小,每次写入文件大小,默认2048字节</param>
 9         public static void UnCompressFile(string compressedFile, string directory, string encryptPassword, bool overWrite = true, int blockSize = 2048)
10         {
11             if (File.Exists(compressedFile) == false) throw new FileNotFoundException("未能找到压缩文件!", compressedFile);
12             if (Directory.Exists(directory) == false) throw new DirectoryNotFoundException("未能找到目标路径!");
13 
14             ///判断路径最后一个字符是否为当前系统的DirectorySeparatorChar
15             if (directory[directory.Length - 1] != Path.DirectorySeparatorChar)
16             {
17                 directory += Path.DirectorySeparatorChar;
18             }
19             try
20             {
21                 ///使用using语句,资源使用完毕,自动释放(类需继承IDispose接口)
22                 ///打开压缩文件进行读取
23                 using (FileStream fs = File.OpenRead(compressedFile))
24                 {
25                     ///创建压缩文件的输入流
26                     using (ZipInputStream inStream = new ZipInputStream(fs))
27                     {
28                         ///加密的密码
29                         inStream.Password = encryptPassword;
30                         ZipEntry entry;
31                         while ((entry = inStream.GetNextEntry()) != null)
32                         {
33                             ///文件的父级目录名称
34                             string directoryName = null;
35                             ///文件的名称,例如git\\git.exe
36                             string entryName = entry.Name;
37 
38                             if (string.IsNullOrWhiteSpace(entryName) == false)
39                             {
40                                 directoryName = Path.GetDirectoryName(entryName) + Path.DirectorySeparatorChar;
41                             }
42                             ///获取文件名称,例如git.exe
43                             string name = Path.GetFileName(entryName);
44                             ///文件的父级目录的绝对路径
45                             string newDirectory = directory + directoryName;
46                             if (Directory.Exists(newDirectory) == false)
47                             {
48                                 Directory.CreateDirectory(newDirectory);
49                             }
50 
51                             if (string.IsNullOrWhiteSpace(name) == false)
52                             {
53                                 ///文件的绝对路径
54                                 string fileName = directory + directoryName + name;
55                                 ///如果覆盖解压或者本地不存在当前文件则进行解压缩
56                                 if (overWrite || File.Exists(fileName) == false)
57                                 {
58                                     using (FileStream fsWrite = File.Create(fileName))
59                                     {
60                                         ///缓存区对象
61                                         byte[] buffer = new byte[blockSize];
62                                         ///读取的字节数
63                                         int sizeRead = 0;
64                                         ///读取完成,解压完成
65                                         do
66                                         {
67                                             ///从流中读取字节,将此数据写入缓存区
68                                             sizeRead = inStream.Read(buffer, 0, buffer.Length);
69                                             ///将字节写入文件流
70                                             fsWrite.Write(buffer, 0, buffer.Length);
71                                         } while (sizeRead > 0);
72                                     }
73                                 }
74                             }
75                         }
76                     }
77                 }
78             }
79             catch (Exception ex)
80             {
81                 LogHelper.Write(ex.ToString());
82             }
83         }

 

四:在Program类Main方法中调用方法

 1、新建几个文件目录用来测试,目录结构如下图

2、编写代码,进行压缩与解压测试,如下

 1 using System;
 2 using System.IO;
 3 
 4 namespace ConsoleCompressApp
 5 {
 6     class Program
 7     {
 8         static void Main(string[] args)
 9         {
10             var projectDirectory = Path.GetFullPath("../..");
11             var directorySeparatorChar = Path.DirectorySeparatorChar;
12             Console.WriteLine("您要压缩Files\\Packages\\git.exe文件么?");
13             if (Console.ReadLine().Trim().ToLower()=="yes")
14             {
15                 SharpZipLibHelper.CompressFile(
16                  fileName: projectDirectory + directorySeparatorChar + "Files" + directorySeparatorChar +
17                  "Packages" + directorySeparatorChar + "git.exe",
18                  compressedFilePath: projectDirectory + directorySeparatorChar + "ZipFiles",
19                  aliasFileName: "",
20                  compressionLevel: 8,
21                  blockSize: 2048,
22                  isEncrypt: true,
23                  encryptPassword: "123");
24             }
25             Console.WriteLine("您要压缩Files整个目录么?");
26             if (Console.ReadLine().Trim().ToLower() == "yes")
27             {
28                 SharpZipLibHelper.CompressDirectory(
29                    directory: projectDirectory + directorySeparatorChar + "Files",
30                    compressedDirectory: projectDirectory + directorySeparatorChar + "ZipDirectory",
31                    aliasFileName: "Files",
32                    isEncrypt: true,
33                    encryptPassword: "456");
34             }
35             Console.WriteLine("您要将ZipDirectory中的Files.zip解压缩到UnZipFiles目录中么?");
36             if (Console.ReadLine().Trim().ToLower() == "yes")
37             {
38                 SharpZipLibHelper.UnCompressFile(compressedFile: projectDirectory + directorySeparatorChar +
39                 "ZipDirectory" + directorySeparatorChar + "Files.zip",
40                 directory: projectDirectory + directorySeparatorChar + "UnZipFiles",
41                 encryptPassword: "456");
42             }
43             Console.WriteLine("恭喜您,操作完成了!");
44             Console.ReadLine();
45         }
46     }
47 }

3、点击启动,进行测试,结果如下:

文件目录如下

 

转载于:https://www.cnblogs.com/Harley520/p/9779197.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值