【随笔系列】C#使用第三方SharpZipLib进行压缩、解压文件
程序员文章站
2022-05-12 13:05:49
近在做项目时用到了文件的批量压缩下载,使用了第三方的SharpZipLib包,后来想到了单个文件的压缩与解压,可能以后会用到相关技术,所以自己熟悉了一下并且借鉴了一些网上的相关代码,自己整理一下,这里我用到的是SharpZipLib 1.0.0版本,这里我新建一个控制台项目来展示。 一:创建项目并安 ......
近在做项目时用到了文件的批量压缩下载,使用了第三方的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 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、新建几个文件目录用来测试,目录结构如下图
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、点击启动,进行测试,结果如下:
文件目录如下
上一篇: 只睡了你一个
下一篇: JavaScript下的date运用