参考
https://blog.csdn.net/lki_suidongdong/article/details/20942977
重点:
实现多级子目录的压缩,类似winrar,可以选择是否排除基准目录
1 public void ZipDirectoryTest() 2 { 3 string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), DateTime.Now.Ticks.ToString()); 4 foreach (string sub in new string[] { "bin", "release", "test", "test\\bin", "" }) 5 { 6 string subPath = System.IO.Path.Combine(path, sub); 7 if (!System.IO.Directory.Exists(subPath)) 8 System.IO.Directory.CreateDirectory(subPath); 9 System.IO.File.WriteAllText(System.IO.Path.Combine(subPath, "1.cs"), ""); 10 System.IO.File.WriteAllText(System.IO.Path.Combine(subPath, "1.txt"), ""); 11 System.IO.File.WriteAllText(System.IO.Path.Combine(subPath, "1.html"), ""); 12 System.IO.File.WriteAllText(System.IO.Path.Combine(subPath, "1.bin"), ""); 13 14 } 15 Console.WriteLine(path); 16 17 new ZipHelper().ZipDirectory(path, "e:\\temp\\tt.zip",false); 18 ZipHelper.UnZip("e:\\temp\\tt.zip", "e:\\temp\\tt2"); 19 //System.IO.Directory.Delete(path, true); 20 //Q.Helper.FileHelper.SelectFile(path); 21 }
代码
1 using System; 2 3 using System.Collections.Generic; 4 5 using System.Linq; 6 7 using System.Text; 8 9 using System.IO; 10 11 using ICSharpCode.SharpZipLib; 12 13 using ICSharpCode.SharpZipLib.Zip; 14 15 #if NETSTANDARD2_0 16 17 using ICSharpCode.SharpZipLib.Checksum; 18 19 #else 20 21 using ICSharpCode.SharpZipLib.Checksums; 22 23 #endif 24 25 26 27 namespace Q.Helper.Zip 28 29 { 30 31 32 33 /// <summary> 34 35 /// 适用与ZIP压缩 36 37 /// </summary> 38 39 public class ZipHelper 40 41 { 42 43 public int Level 44 45 { 46 47 get; set; 48 49 } 50 51 #region 压缩 52 53 54 55 /// <summary> 56 57 /// 递归压缩文件夹的内部方法(排除相对路径) 58 59 /// </summary> 60 61 /// <param name="folderToZip">要压缩的文件夹路径</param> 62 63 /// <param name="zipStream">压缩输出流</param> 64 65 /// <param name="parentFolderName">此文件夹的上级文件夹</param> 66 67 /// <param name="includeFloderName">是否包含目录名</param> 68 69 /// <returns></returns> 70 71 private bool ZipDirectory(string folderToZip, ZipOutputStream zipStream, string parentFolderName, bool createBaseFolder = true) 72 73 { 74 75 folderToZip = folderToZip.Replace("\\", "/"); 76 77 bool result = true; 78 79 string[] folders, files; 80 81 ZipEntry ent = null; 82 83 FileStream fs = null; 84 85 Crc32 crc = new Crc32(); 86 87 88 89 try 90 91 { 92 93 string entPath = Path.Combine(parentFolderName, Path.GetFileName(folderToZip) + "/").Replace("\\", "/"); 94 95 if (!createBaseFolder) 96 97 entPath = entPath.Substring(entPath.IndexOf("/") + 1); 98 99 if (!string.IsNullOrEmpty(entPath)) 100 101 { 102 103 ent = new ZipEntry(entPath); 104 105 Console.WriteLine(entPath); 106 107 zipStream.PutNextEntry(ent); 108 109 zipStream.Flush(); 110 111 } 112 113 files = Directory.GetFiles(folderToZip); 114 115 foreach (string file in files) 116 117 { 118 119 fs = File.OpenRead(file); 120 121 122 123 byte[] buffer = new byte[fs.Length]; 124 125 fs.Read(buffer, 0, buffer.Length); 126 127 entPath = Path.Combine(parentFolderName, Path.GetFileName(folderToZip) + "/" + Path.GetFileName(file)).Replace("\\", "/"); 128 129 if (!createBaseFolder) 130 131 entPath = entPath.Substring(entPath.IndexOf("/") + 1); 132 133 Console.WriteLine(entPath); 134 135 ent = new ZipEntry(entPath); 136 137 ent.DateTime = DateTime.Now; 138 139 ent.Size = fs.Length; 140 141 142 143 fs.Close(); 144 145 146 147 crc.Reset(); 148 149 crc.Update(buffer); 150 151 152 153 ent.Crc = crc.Value; 154 155 zipStream.PutNextEntry(ent); 156 157 zipStream.Write(buffer, 0, buffer.Length); 158 159 } 160 161 162 163 } 164 165 catch (Exception ex) 166 167 { 168 169 result = false; 170 171 throw ex; 172 173 } 174 175 finally 176 177 { 178 179 if (fs != null) 180 181 { 182 183 fs.Close(); 184 185 fs.Dispose(); 186 187 } 188 189 if (ent != null) 190 191 { 192 193 ent = null; 194 195 } 196 197 GC.Collect(); 198 199 GC.Collect(1); 200 201 } 202 203 204 205 folders = Directory.GetDirectories(folderToZip); 206 207 //多级递归时需要记住相对目录 208 209 foreach (string folder in folders) 210 211 { 212 213 if (!ZipDirectory(folder, zipStream, Path.Combine(parentFolderName, Path.GetFileName(folderToZip)), createBaseFolder)) 214 215 return false; 216 217 } 218 219 return result; 220 221 } 222 223 224 225 /// <summary> 226 227 /// 压缩文件夹 228 229 /// </summary> 230 231 /// <param name="folderToZip">要压缩的文件夹路径</param> 232 233 /// <param name="zipedFile">压缩文件完整路径</param> 234 235 /// <param name="password">密码</param> 236 237 /// <returns>是否压缩成功</returns> 238 239 public bool ZipDirectory(string folderToZip, string zipedFile, string password, bool includeFloderName = true) 240 241 { 242 243 bool result = false; 244 245 if (!Directory.Exists(folderToZip)) 246 247 return result; 248 249 250 251 ZipOutputStream zipStream = new ZipOutputStream(File.Create(zipedFile)); 252 253 zipStream.SetLevel(Level); 254 255 if (!string.IsNullOrEmpty(password)) zipStream.Password = password; 256 257 258 259 result = ZipDirectory(folderToZip, zipStream, "", includeFloderName); 260 261 262 263 zipStream.Finish(); 264 265 zipStream.Close(); 266 267 268 269 return result; 270 271 } 272 273 274 275 /// <summary> 276 277 /// 压缩文件夹 278 279 /// </summary> 280 281 /// <param name="folderToZip">要压缩的文件夹路径</param> 282 283 /// <param name="zipedFile">压缩文件完整路径</param> 284 285 /// <returns>是否压缩成功</returns> 286 287 public bool ZipDirectory(string folderToZip, string zipedFile, bool includeFloderName = true) 288 289 { 290 291 bool result = ZipDirectory(folderToZip, zipedFile, "", includeFloderName); 292 293 return result; 294 295 } 296 297 298 299 /// <summary> 300 301 /// 压缩文件 302 303 /// </summary> 304 305 /// <param name="fileToZip">要压缩的文件全名</param> 306 307 /// <param name="zipedFile">压缩后的文件名</param> 308 309 /// <param name="password">密码</param> 310 311 /// <returns>压缩结果</returns> 312 313 public bool ZipFile(string fileToZip, string zipedFile, string password) 314 315 { 316 317 bool result = true; 318 319 ZipOutputStream zipStream = null; 320 321 FileStream fs = null; 322 323 ZipEntry ent = null; 324 325 326 327 if (!File.Exists(fileToZip)) 328 329 return false; 330 331 332 333 try 334 335 { 336 337 fs = File.OpenRead(fileToZip); 338 339 byte[] buffer = new byte[fs.Length]; 340 341 fs.Read(buffer, 0, buffer.Length); 342 343 fs.Close(); 344 345 346 347 fs = File.Create(zipedFile); 348 349 zipStream = new ZipOutputStream(fs); 350 351 if (!string.IsNullOrEmpty(password)) zipStream.Password = password; 352 353 ent = new ZipEntry(Path.GetFileName(fileToZip)); 354 355 zipStream.PutNextEntry(ent); 356 357 zipStream.SetLevel(Level); 358 359 360 361 zipStream.Write(buffer, 0, buffer.Length); 362 363 364 365 } 366 367 catch 368 369 { 370 371 result = false; 372 373 } 374 375 finally 376 377 { 378 379 if (zipStream != null) 380 381 { 382 383 zipStream.Finish(); 384 385 zipStream.Close(); 386 387 } 388 389 if (ent != null) 390 391 { 392 393 ent = null; 394 395 } 396 397 if (fs != null) 398 399 { 400 401 fs.Close(); 402 403 fs.Dispose(); 404 405 } 406 407 } 408 409 GC.Collect(); 410 411 GC.Collect(1); 412 413 414 415 return result; 416 417 } 418 419 420 421 /// <summary> 422 423 /// 压缩文件 424 425 /// </summary> 426 427 /// <param name="fileToZip">要压缩的文件全名</param> 428 429 /// <param name="zipedFile">压缩后的文件名</param> 430 431 /// <returns>压缩结果</returns> 432 433 public bool ZipFile(string fileToZip, string zipedFile) 434 435 { 436 437 bool result = ZipFile(fileToZip, zipedFile, null); 438 439 return result; 440 441 } 442 443 444 445 /// <summary> 446 447 /// 压缩文件或文件夹 448 449 /// </summary> 450 451 /// <param name="fileToZip">要压缩的路径</param> 452 453 /// <param name="zipedFile">压缩后的文件名</param> 454 455 /// <param name="password">密码</param> 456 457 /// <returns>压缩结果</returns> 458 459 public bool Zip(string fileToZip, string zipedFile, string password) 460 461 { 462 463 bool result = false; 464 465 if (Directory.Exists(fileToZip)) 466 467 result = ZipDirectory(fileToZip, zipedFile, password); 468 469 else if (File.Exists(fileToZip)) 470 471 result = ZipFile(fileToZip, zipedFile, password); 472 473 474 475 return result; 476 477 } 478 479 480 481 /// <summary> 482 483 /// 压缩文件或文件夹 484 485 /// </summary> 486 487 /// <param name="fileToZip">要压缩的路径</param> 488 489 /// <param name="zipedFile">压缩后的文件名</param> 490 491 /// <returns>压缩结果</returns> 492 493 public bool Zip(string fileToZip, string zipedFile) 494 495 { 496 497 bool result = Zip(fileToZip, zipedFile, null); 498 499 return result; 500 501 502 503 } 504 505 506 507 #endregion 508 509 510 511 #region 解压 512 513 514 515 /// <summary> 516 517 /// 解压功能(解压压缩文件到指定目录) 518 519 /// </summary> 520 521 /// <param name="fileToUnZip">待解压的文件</param> 522 523 /// <param name="zipedFolder">指定解压目标目录</param> 524 525 /// <param name="password">密码</param> 526 527 /// <returns>解压结果</returns> 528 529 public static bool UnZip(string fileToUnZip, string zipedFolder, string password) 530 531 { 532 533 bool result = true; 534 535 536 537 ZipInputStream zipStream = null; 538 539 ZipEntry ent = null; 540 541 string fileName; 542 543 544 545 if (!File.Exists(fileToUnZip)) 546 547 return false; 548 549 550 551 if (!Directory.Exists(zipedFolder)) 552 553 Directory.CreateDirectory(zipedFolder); 554 555 556 557 try 558 559 { 560 561 zipStream = new ZipInputStream(File.OpenRead(fileToUnZip)); 562 563 if (!string.IsNullOrEmpty(password)) zipStream.Password = password; 564 565 while ((ent = zipStream.GetNextEntry()) != null) 566 567 { 568 569 if (!string.IsNullOrEmpty(ent.Name)) 570 571 { 572 573 fileName = Path.Combine(zipedFolder, ent.Name); 574 575 fileName = fileName.Replace('/', '\\');//change by Mr.HopeGi 576 577 578 579 if (fileName.EndsWith("\\")) 580 581 { 582 583 Directory.CreateDirectory(fileName); 584 585 continue; 586 587 } 588 589 using (FileStream fs = File.Create(fileName)) 590 591 { 592 593 int size = 2048; 594 595 byte[] data = new byte[size]; 596 597 while (true) 598 599 { 600 601 602 603 size = zipStream.Read(data, 0, data.Length); 604 605 if (size > 0) 606 607 fs.Write(data, 0, data.Length); 608 609 else 610 611 break; 612 613 } 614 615 fs.Flush(); 616 617 618 619 fs.Close(); 620 621 new FileInfo(fileName).LastWriteTime = ent.DateTime; 622 623 } 624 625 626 627 } 628 629 } 630 631 } 632 633 catch 634 635 { 636 637 result = false; 638 639 } 640 641 finally 642 643 { 644 645 646 647 if (zipStream != null) 648 649 { 650 651 zipStream.Close(); 652 653 zipStream.Dispose(); 654 655 } 656 657 if (ent != null) 658 659 { 660 661 ent = null; 662 663 } 664 665 GC.Collect(); 666 667 GC.Collect(1); 668 669 } 670 671 return result; 672 673 } 674 675 676 677 /// <summary> 678 679 /// 解压功能(解压压缩文件到指定目录) 680 681 /// </summary> 682 683 /// <param name="fileToUnZip">待解压的文件</param> 684 685 /// <param name="zipedFolder">指定解压目标目录</param> 686 687 /// <returns>解压结果</returns> 688 689 public static bool UnZip(string fileToUnZip, string zipedFolder) 690 691 { 692 693 bool result = UnZip(fileToUnZip, zipedFolder, null); 694 695 return result; 696 697 } 698 699 700 701 #endregion 702 703 } 704 705 }