【C#公共帮助类】ZipHelper 压缩和解压帮助类,经过实战总结出来的代码
本文档基于ICSharpCode.SharpZipLib.dll的封装,常用的解压和压缩方法都已经涵盖在内,都是经过项目实战积累下来的
欢迎传播分享,必须保持原作者的信息,但禁止将该文档直接用于商业盈利。
本人自从几年前走上编程之路,一直致力于收集和总结出好用的框架和通用类库,不管是微软自己的还是第三方的只要实际项目中好用且可以解决实际问题那都会收集好,编写好文章和别人一起分享,这样自己学到了,别人也能学到知识,当今社会很需要知识的搬运工。
Email:707055073@qq.com
本文章地址: http://www.cnblogs.com/wohexiaocai/p/5469253.html
1.基本介绍
由于项目中需要用到各种压缩将文件进行压缩下载,减少网络的带宽,所以压缩是一个非常常见的功能,对于压缩微软自己也提供了一些类库
- 微软自带压缩类ZipArchive类,适合NET FrameWork4.5才可以使用
- 调用压缩软件命令执行压缩动作,这个就需要电脑本身安装压缩软件了
- 使用第三方的压缩dll文件,一般使用最多的是(ICSharpCode.SharpZipLib.dll),下载dll ICSharpCode.SharpZipLib.zip
2.实际项目
- 压缩单个文件,需要指定压缩等级
- 压缩单个文件夹,需要指定压缩等级
- 压缩多个文件或者多个文件夹
- 对压缩包进行加密【用的较少,实际情况也有】
- 直接解压,无需密码
- 需要密码解压
2.1 压缩单个文件
写了两个方法,可以指定压缩等级,这样你的压缩包大小就不一样了
2.2 压缩单个文件夹
public void ZipDir(string dirToZip, string zipedFileName, int compressionLevel = 9)
2.3 压缩多个文件或者文件夹
public bool ZipManyFilesOrDictorys(IEnumerable<string> folderOrFileList, string zipedFile, string password)
2.4 对压缩包进行加密
public bool ZipManyFilesOrDictorys(IEnumerable<string> folderOrFileList, string zipedFile, string password)
2.5 直接解压,无需密码
public void UnZip(string zipFilePath, string unZipDir)
3.演示图
3.ZipHelper下载
1 //------------------------------------------------------------------------------------- 2 // All Rights Reserved , Copyright (C) 2016 , ZTO , Ltd . 3 //------------------------------------------------------------------------------------- 4 5 using System; 6 using System.Collections; 7 using System.Collections.Generic; 8 using System.IO; 9 10 namespace ZTO.PicTest.Utilities 11 { 12 using ICSharpCode.SharpZipLib.Checksums; 13 using ICSharpCode.SharpZipLib.Zip; 14 15 /// <summary> 16 /// Zip压缩帮助类 17 /// 18 /// 修改纪录 19 /// 20 /// 2015-09-16 版本:1.0 YangHengLian 创建主键,注意命名空间的排序。 21 /// 2016-5-7 YangHengLian增加了可以支持多个文件或者多个文件夹打包成一个zip文件 22 /// 23 /// 版本:1.0 24 /// 25 /// <author> 26 /// <name>YangHengLian</name> 27 /// <date>2015-09-16</date> 28 /// </author> 29 /// </summary> 30 public class ZipHelper 31 { 32 /// <summary> 33 /// 压缩文件夹 34 /// </summary> 35 /// <param name="dirToZip"></param> 36 /// <param name="zipedFileName"></param> 37 /// <param name="compressionLevel">压缩率0(无压缩)9(压缩率最高)</param> 38 public void ZipDir(string dirToZip, string zipedFileName, int compressionLevel = 9) 39 { 40 if (Path.GetExtension(zipedFileName) != ".zip") 41 { 42 zipedFileName = zipedFileName + ".zip"; 43 } 44 using (var zipoutputstream = new ZipOutputStream(File.Create(zipedFileName))) 45 { 46 zipoutputstream.SetLevel(compressionLevel); 47 Crc32 crc = new Crc32(); 48 Hashtable fileList = GetAllFies(dirToZip); 49 foreach (DictionaryEntry item in fileList) 50 { 51 FileStream fs = new FileStream(item.Key.ToString(), FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 52 byte[] buffer = new byte[fs.Length]; 53 fs.Read(buffer, 0, buffer.Length); 54 // ZipEntry entry = new ZipEntry(item.Key.ToString().Substring(dirToZip.Length + 1)); 55 ZipEntry entry = new ZipEntry(Path.GetFileName(item.Key.ToString())) 56 { 57 DateTime = (DateTime) item.Value, 58 Size = fs.Length 59 }; 60 fs.Close(); 61 crc.Reset(); 62 crc.Update(buffer); 63 entry.Crc = crc.Value; 64 zipoutputstream.PutNextEntry(entry); 65 zipoutputstream.Write(buffer, 0, buffer.Length); 66 } 67 } 68 } 69 70 /// <summary> 71 /// 获取所有文件 72 /// </summary> 73 /// <returns></returns> 74 public Hashtable GetAllFies(string dir) 75 { 76 Hashtable filesList = new Hashtable(); 77 DirectoryInfo fileDire = new DirectoryInfo(dir); 78 if (!fileDire.Exists) 79 { 80 throw new FileNotFoundException("目录:" + fileDire.FullName + "没有找到!"); 81 } 82 83 GetAllDirFiles(fileDire, filesList); 84 GetAllDirsFiles(fileDire.GetDirectories(), filesList); 85 return filesList; 86 } 87 88 /// <summary> 89 /// 获取一个文件夹下的所有文件夹里的文件 90 /// </summary> 91 /// <param name="dirs"></param> 92 /// <param name="filesList"></param> 93 public void GetAllDirsFiles(IEnumerable<DirectoryInfo> dirs, Hashtable filesList) 94 { 95 foreach (DirectoryInfo dir in dirs) 96 { 97 foreach (FileInfo file in dir.GetFiles("*.*")) 98 { 99 filesList.Add(file.FullName, file.LastWriteTime); 100 } 101 GetAllDirsFiles(dir.GetDirectories(), filesList); 102 } 103 } 104 105 /// <summary> 106 /// 获取一个文件夹下的文件 107 /// </summary> 108 /// <param name="dir">目录名称</param> 109 /// <param name="filesList">文件列表HastTable</param> 110 public static void GetAllDirFiles(DirectoryInfo dir, Hashtable filesList) 111 { 112 foreach (FileInfo file in dir.GetFiles("*.*")) 113 { 114 filesList.Add(file.FullName, file.LastWriteTime); 115 } 116 } 117 118 /// <summary> 119 /// 功能:解压zip格式的文件。 120 /// </summary> 121 /// <param name="zipFilePath">压缩文件路径</param> 122 /// <param name="unZipDir">解压文件存放路径,为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹</param> 123 /// <returns>解压是否成功</returns> 124 public void UnZip(string zipFilePath, string unZipDir) 125 { 126 if (zipFilePath == string.Empty) 127 { 128 throw new Exception("压缩文件不能为空!"); 129 } 130 if (!File.Exists(zipFilePath)) 131 { 132 throw new FileNotFoundException("压缩文件不存在!"); 133 } 134 //解压文件夹为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹 135 if (unZipDir == string.Empty) 136 unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), Path.GetFileNameWithoutExtension(zipFilePath)); 137 if (!unZipDir.EndsWith("/")) 138 unZipDir += "/"; 139 if (!Directory.Exists(unZipDir)) 140 Directory.CreateDirectory(unZipDir); 141 142 using (var s = new ZipInputStream(File.OpenRead(zipFilePath))) 143 { 144 145 ZipEntry theEntry; 146 while ((theEntry = s.GetNextEntry()) != null) 147 { 148 string directoryName = Path.GetDirectoryName(theEntry.Name); 149 string fileName = Path.GetFileName(theEntry.Name); 150 if (!string.IsNullOrEmpty(directoryName)) 151 { 152 Directory.CreateDirectory(unZipDir + directoryName); 153 } 154 if (directoryName != null && !directoryName.EndsWith("/")) 155 { 156 } 157 if (fileName != String.Empty) 158 { 159 using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name)) 160 { 161 162 int size; 163 byte[] data = new byte[2048]; 164 while (true) 165 { 166 size = s.Read(data, 0, data.Length); 167 if (size > 0) 168 { 169 streamWriter.Write(data, 0, size); 170 } 171 else 172 { 173 break; 174 } 175 } 176 } 177 } 178 } 179 } 180 } 181 182 /// <summary> 183 /// 压缩单个文件 184 /// </summary> 185 /// <param name="filePath">被压缩的文件名称(包含文件路径),文件的全路径</param> 186 /// <param name="zipedFileName">压缩后的文件名称(包含文件路径),保存的文件名称</param> 187 /// <param name="compressionLevel">压缩率0(无压缩)到 9(压缩率最高)</param> 188 public void ZipFile(string filePath, string zipedFileName, int compressionLevel = 9) 189 { 190 // 如果文件没有找到,则报错 191 if (!File.Exists(filePath)) 192 { 193 throw new FileNotFoundException("文件:" + filePath + "没有找到!"); 194 } 195 // 如果压缩后名字为空就默认使用源文件名称作为压缩文件名称 196 if (string.IsNullOrEmpty(zipedFileName)) 197 { 198 string oldValue = Path.GetFileName(filePath); 199 if (oldValue != null) 200 { 201 zipedFileName = filePath.Replace(oldValue, "") + Path.GetFileNameWithoutExtension(filePath) + ".zip"; 202 } 203 } 204 // 如果压缩后的文件名称后缀名不是zip,就是加上zip,防止是一个乱码文件 205 if (Path.GetExtension(zipedFileName) != ".zip") 206 { 207 zipedFileName = zipedFileName + ".zip"; 208 } 209 // 如果指定位置目录不存在,创建该目录 C:\Users\yhl\Desktop\大汉三通 210 string zipedDir = zipedFileName.Substring(0, zipedFileName.LastIndexOf("\\", StringComparison.Ordinal)); 211 if (!Directory.Exists(zipedDir)) 212 { 213 Directory.CreateDirectory(zipedDir); 214 } 215 // 被压缩文件名称 216 string filename = filePath.Substring(filePath.LastIndexOf("\\", StringComparison.Ordinal) + 1); 217 var streamToZip = new FileStream(filePath, FileMode.Open, FileAccess.Read); 218 var zipFile = File.Create(zipedFileName); 219 var zipStream = new ZipOutputStream(zipFile); 220 var zipEntry = new ZipEntry(filename); 221 zipStream.PutNextEntry(zipEntry); 222 zipStream.SetLevel(compressionLevel); 223 var buffer = new byte[2048]; 224 Int32 size = streamToZip.Read(buffer, 0, buffer.Length); 225 zipStream.Write(buffer, 0, size); 226 try 227 { 228 while (size < streamToZip.Length) 229 { 230 int sizeRead = streamToZip.Read(buffer, 0, buffer.Length); 231 zipStream.Write(buffer, 0, sizeRead); 232 size += sizeRead; 233 } 234 } 235 finally 236 { 237 zipStream.Finish(); 238 zipStream.Close(); 239 streamToZip.Close(); 240 } 241 } 242 243 /// <summary> 244 /// 压缩单个文件 245 /// </summary> 246 /// <param name="fileToZip">要进行压缩的文件名,全路径</param> 247 /// <param name="zipedFile">压缩后生成的压缩文件名,全路径</param> 248 public void ZipFile(string fileToZip, string zipedFile) 249 { 250 // 如果文件没有找到,则报错 251 if (!File.Exists(fileToZip)) 252 { 253 throw new FileNotFoundException("指定要压缩的文件: " + fileToZip + " 不存在!"); 254 } 255 using (FileStream fileStream = File.OpenRead(fileToZip)) 256 { 257 byte[] buffer = new byte[fileStream.Length]; 258 fileStream.Read(buffer, 0, buffer.Length); 259 fileStream.Close(); 260 using (FileStream zipFile = File.Create(zipedFile)) 261 { 262 using (ZipOutputStream zipOutputStream = new ZipOutputStream(zipFile)) 263 { 264 // string fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\") + 1); 265 string fileName = Path.GetFileName(fileToZip); 266 var zipEntry = new ZipEntry(fileName) 267 { 268 DateTime = DateTime.Now, 269 IsUnicodeText = true 270 }; 271 zipOutputStream.PutNextEntry(zipEntry); 272 zipOutputStream.SetLevel(5); 273 zipOutputStream.Write(buffer, 0, buffer.Length); 274 zipOutputStream.Finish(); 275 zipOutputStream.Close(); 276 } 277 } 278 } 279 } 280 281 /// <summary> 282 /// 压缩多个目录或文件 283 /// </summary> 284 /// <param name="folderOrFileList">待压缩的文件夹或者文件,全路径格式,是一个集合</param> 285 /// <param name="zipedFile">压缩后的文件名,全路径格式</param> 286 /// <param name="password">压宿密码</param> 287 /// <returns></returns> 288 public bool ZipManyFilesOrDictorys(IEnumerable<string> folderOrFileList, string zipedFile, string password) 289 { 290 bool res = true; 291 using (var s = new ZipOutputStream(File.Create(zipedFile))) 292 { 293 s.SetLevel(6); 294 if (!string.IsNullOrEmpty(password)) 295 { 296 s.Password = password; 297 } 298 foreach (string fileOrDir in folderOrFileList) 299 { 300 //是文件夹 301 if (Directory.Exists(fileOrDir)) 302 { 303 res = ZipFileDictory(fileOrDir, s, ""); 304 } 305 else 306 { 307 //文件 308 res = ZipFileWithStream(fileOrDir, s); 309 } 310 } 311 s.Finish(); 312 s.Close(); 313 return res; 314 } 315 } 316 317 /// <summary> 318 /// 带压缩流压缩单个文件 319 /// </summary> 320 /// <param name="fileToZip">要进行压缩的文件名</param> 321 /// <param name="zipStream"></param> 322 /// <returns></returns> 323 private bool ZipFileWithStream(string fileToZip, ZipOutputStream zipStream) 324 { 325 //如果文件没有找到,则报错 326 if (!File.Exists(fileToZip)) 327 { 328 throw new FileNotFoundException("指定要压缩的文件: " + fileToZip + " 不存在!"); 329 } 330 //FileStream fs = null; 331 FileStream zipFile = null; 332 ZipEntry zipEntry = null; 333 bool res = true; 334 try 335 { 336 zipFile = File.OpenRead(fileToZip); 337 byte[] buffer = new byte[zipFile.Length]; 338 zipFile.Read(buffer, 0, buffer.Length); 339 zipFile.Close(); 340 zipEntry = new ZipEntry(Path.GetFileName(fileToZip)); 341 zipStream.PutNextEntry(zipEntry); 342 zipStream.Write(buffer, 0, buffer.Length); 343 } 344 catch 345 { 346 res = false; 347 } 348 finally 349 { 350 if (zipEntry != null) 351 { 352 } 353 354 if (zipFile != null) 355 { 356 zipFile.Close(); 357 } 358 GC.Collect(); 359 GC.Collect(1); 360 } 361 return res; 362 363 } 364 365 /// <summary> 366 /// 递归压缩文件夹方法 367 /// </summary> 368 /// <param name="folderToZip"></param> 369 /// <param name="s"></param> 370 /// <param name="parentFolderName"></param> 371 private bool ZipFileDictory(string folderToZip, ZipOutputStream s, string parentFolderName) 372 { 373 bool res = true; 374 ZipEntry entry = null; 375 FileStream fs = null; 376 Crc32 crc = new Crc32(); 377 try 378 { 379 //创建当前文件夹 380 entry = new ZipEntry(Path.Combine(parentFolderName, Path.GetFileName(folderToZip) + "/")); //加上 “/” 才会当成是文件夹创建 381 s.PutNextEntry(entry); 382 s.Flush(); 383 //先压缩文件,再递归压缩文件夹 384 var filenames = Directory.GetFiles(folderToZip); 385 foreach (string file in filenames) 386 { 387 //打开压缩文件 388 fs = File.OpenRead(file); 389 byte[] buffer = new byte[fs.Length]; 390 fs.Read(buffer, 0, buffer.Length); 391 entry = new ZipEntry(Path.Combine(parentFolderName, Path.GetFileName(folderToZip) + "/" + Path.GetFileName(file))); 392 entry.DateTime = DateTime.Now; 393 entry.Size = fs.Length; 394 fs.Close(); 395 crc.Reset(); 396 crc.Update(buffer); 397 entry.Crc = crc.Value; 398 s.PutNextEntry(entry); 399 s.Write(buffer, 0, buffer.Length); 400 } 401 } 402 catch 403 { 404 res = false; 405 } 406 finally 407 { 408 if (fs != null) 409 { 410 fs.Close(); 411 } 412 if (entry != null) 413 { 414 } 415 GC.Collect(); 416 GC.Collect(1); 417 } 418 var folders = Directory.GetDirectories(folderToZip); 419 foreach (string folder in folders) 420 { 421 if (!ZipFileDictory(folder, s, Path.Combine(parentFolderName, Path.GetFileName(folderToZip)))) 422 { 423 return false; 424 } 425 } 426 return res; 427 } 428 } 429 }
慢慢积累,你的这些代码都是你的财富,可以帮你提高工作效率,勤勤恳恳的干好每件事情,点滴积累,开心编程。