近在做项目时用到了文件的批量压缩下载,使用了第三方的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 try12 {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 else23 {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 try16 {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 do45 {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 try14 {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 ///判断路径最后一个字符是否为当前系统的DirectorySeparatorChar47 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 else63 {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 ///判断路径最后一个字符是否为当前系统的DirectorySeparatorChar15 if (directory[directory.Length - 1] != Path.DirectorySeparatorChar)16 {17 directory += Path.DirectorySeparatorChar;18 }19 try20 {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.exe36 string entryName = entry.Name;37 38 if (string.IsNullOrWhiteSpace(entryName) == false)39 {40 directoryName = Path.GetDirectoryName(entryName) + Path.DirectorySeparatorChar;41 }42 ///获取文件名称,例如git.exe43 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 do66 {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、点击启动,进行测试,结果如下:

文件目录如下
