欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

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

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

 

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

1、新建控制台项目consolecompressapp

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

2、通过visualstudio菜单中工具->nuget包管理器->程序包管理控制台安装sharpziplib包

命令是install-package sharpziplib,如下图显示,已安装完成。

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

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

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

选择第一个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                             compresstraversal(directory, outstream, "");
31                         }
32                     }
33                 }
34             }
35             catch (system.exception ex)
36             {
37                 loghelper.write(ex.tostring());
38             }
39         }
40 
41         /// <summary>
42         /// 递归遍历目录
43         /// </summary>
44         private static void compresstraversal(string directory, zipoutputstream outstream, string parentdirectory)
45         {
46             ///判断路径最后一个字符是否为当前系统的directoryseparatorchar
47             if (directory[directory.length - 1] != path.directoryseparatorchar)
48             {
49                 directory += path.directoryseparatorchar;
50             }
51             crc32 crc = new crc32();
52             var fileordirectory = directory.getfilesystementries(directory);
53             ///遍历文件与目录
54             foreach (var item in fileordirectory)
55             {
56                 ///判断是否为目录
57                 if (directory.exists(item))
58                 {
59                     compresstraversal(item, outstream, (parentdirectory + item.substring(item.lastindexof(path.directoryseparatorchar) + 1) + path.directoryseparatorchar));
60                 }
61                 ///压缩文件
62                 else
63                 {
64                     using (filestream instream = file.openread(item))
65                     {
66                         ///缓存区对象
67                         byte[] buffer = new byte[instream.length];
68                         ///从文件流中读取字节,将该数据写入缓存区
69                         instream.read(buffer, 0, buffer.length);
70                         ///获取该文件名称(附带文件目录结构,例如git\\git.exe)
71                         string filename = parentdirectory + item.substring(item.lastindexof(path.directoryseparatorchar) + 1);
72                         ///创建zip条目
73                         zipentry entry = new zipentry(filename);
74                         entry.datetime = datetime.now;
75                         entry.size = instream.length;
76 
77                         crc.reset();
78                         crc.update(buffer);
79 
80                         entry.crc = crc.value;
81 
82                         outstream.putnextentry(entry);
83                         outstream.write(buffer, 0, buffer.length);
84                     }
85                 }
86             }
87         }

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、新建几个文件目录用来测试,目录结构如下图

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

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、点击启动,进行测试,结果如下:

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

文件目录如下

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