星火批注
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 3 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. using ICSharpCode.SharpZipLib.Checksums;
  2. using ICSharpCode.SharpZipLib.Zip;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. namespace Common.system
  7. {
  8. /// <summary>
  9. /// 适用与ZIP压缩
  10. /// </summary>
  11. public class ZipHelper
  12. {
  13. #region 压缩
  14. /// <summary>
  15. /// 递归压缩文件夹的内部方法
  16. /// </summary>
  17. /// <param name="folderToZip">要压缩的文件夹路径</param>
  18. /// <param name="zipStream">压缩输出流</param>
  19. /// <param name="parentFolderName">此文件夹的上级文件夹</param>
  20. /// <returns></returns>
  21. private static bool ZipDirectory(string folderToZip, ZipOutputStream zipStream, string parentFolderName)
  22. {
  23. bool result = true;
  24. string[] folders, files;
  25. ZipEntry ent = null;
  26. FileStream fs = null;
  27. Crc32 crc = new Crc32();
  28. try
  29. {
  30. ent = new ZipEntry(Path.Combine(parentFolderName, Path.GetFileName(folderToZip) + "/"));
  31. zipStream.PutNextEntry(ent);
  32. zipStream.Flush();
  33. files = Directory.GetFiles(folderToZip);
  34. foreach (string file in files)
  35. {
  36. fs = File.OpenRead(file);
  37. byte[] buffer = new byte[fs.Length];
  38. fs.Read(buffer, 0, buffer.Length);
  39. ent = new ZipEntry(Path.Combine(parentFolderName, Path.GetFileName(folderToZip) + "/" + Path.GetFileName(file)))
  40. {
  41. DateTime = DateTime.Now,
  42. Size = fs.Length
  43. };
  44. fs.Close();
  45. crc.Reset();
  46. crc.Update(buffer);
  47. ent.Crc = crc.Value;
  48. zipStream.PutNextEntry(ent);
  49. zipStream.Write(buffer, 0, buffer.Length);
  50. }
  51. }
  52. catch
  53. {
  54. result = false;
  55. }
  56. finally
  57. {
  58. if (fs != null)
  59. {
  60. fs.Close();
  61. fs.Dispose();
  62. }
  63. if (ent != null)
  64. {
  65. ent = null;
  66. }
  67. GC.Collect();
  68. GC.Collect(1);
  69. }
  70. folders = Directory.GetDirectories(folderToZip);
  71. foreach (string folder in folders)
  72. {
  73. if (!ZipDirectory(folder, zipStream, folderToZip))
  74. {
  75. return false;
  76. }
  77. }
  78. return result;
  79. }
  80. /// <summary>
  81. /// 压缩文件夹
  82. /// </summary>
  83. /// <param name="folderToZip">要压缩的文件夹路径</param>
  84. /// <param name="zipedFile">压缩文件完整路径</param>
  85. /// <param name="password">密码</param>
  86. /// <returns>是否压缩成功</returns>
  87. public static bool ZipDirectory(string folderToZip, string zipedFile, string password)
  88. {
  89. bool result = false;
  90. if (!Directory.Exists(folderToZip))
  91. {
  92. return result;
  93. }
  94. ZipOutputStream zipStream = new ZipOutputStream(File.Create(zipedFile));
  95. zipStream.SetLevel(6);
  96. if (!string.IsNullOrEmpty(password))
  97. {
  98. zipStream.Password = password;
  99. }
  100. result = ZipDirectory(folderToZip, zipStream, "");
  101. zipStream.Finish();
  102. zipStream.Close();
  103. return result;
  104. }
  105. /// <summary>
  106. /// 压缩文件夹
  107. /// </summary>
  108. /// <param name="folderToZip">要压缩的文件夹路径</param>
  109. /// <param name="zipedFile">压缩文件完整路径</param>
  110. /// <returns>是否压缩成功</returns>
  111. public static bool ZipDirectory(string folderToZip, string zipedFile)
  112. {
  113. bool result = ZipDirectory(folderToZip, zipedFile, null);
  114. return result;
  115. }
  116. /// <summary>
  117. /// 压缩文件
  118. /// </summary>
  119. /// <param name="fileToZip">要压缩的文件全名</param>
  120. /// <param name="zipedFile">压缩后的文件名</param>
  121. /// <param name="password">密码</param>
  122. /// <returns>压缩结果</returns>
  123. public static bool ZipFile(string fileToZip, string zipedFile, string password)
  124. {
  125. bool result = true;
  126. ZipOutputStream zipStream = null;
  127. FileStream fs = null;
  128. ZipEntry ent = null;
  129. if (!File.Exists(fileToZip))
  130. {
  131. return false;
  132. }
  133. try
  134. {
  135. fs = File.OpenRead(fileToZip);
  136. byte[] buffer = new byte[fs.Length];
  137. fs.Read(buffer, 0, buffer.Length);
  138. fs.Close();
  139. fs = File.Create(zipedFile);
  140. zipStream = new ZipOutputStream(fs);
  141. if (!string.IsNullOrEmpty(password))
  142. {
  143. zipStream.Password = password;
  144. }
  145. ent = new ZipEntry(Path.GetFileName(fileToZip));
  146. zipStream.PutNextEntry(ent);
  147. zipStream.SetLevel(6);
  148. zipStream.Write(buffer, 0, buffer.Length);
  149. }
  150. catch
  151. {
  152. result = false;
  153. }
  154. finally
  155. {
  156. if (zipStream != null)
  157. {
  158. zipStream.Finish();
  159. zipStream.Close();
  160. }
  161. if (ent != null)
  162. {
  163. ent = null;
  164. }
  165. if (fs != null)
  166. {
  167. fs.Close();
  168. fs.Dispose();
  169. }
  170. }
  171. GC.Collect();
  172. GC.Collect(1);
  173. return result;
  174. }
  175. /// <summary>
  176. /// 压缩文件
  177. /// </summary>
  178. /// <param name="fileToZip">要压缩的文件全名</param>
  179. /// <param name="zipedFile">压缩后的文件名</param>
  180. /// <returns>压缩结果</returns>
  181. public static bool ZipFile(string fileToZip, string zipedFile)
  182. {
  183. bool result = ZipFile(fileToZip, zipedFile, null);
  184. return result;
  185. }
  186. /// <summary>
  187. /// 压缩文件或文件夹
  188. /// </summary>
  189. /// <param name="fileToZip">要压缩的路径</param>
  190. /// <param name="zipedFile">压缩后的文件名</param>
  191. /// <param name="password">密码</param>
  192. /// <returns>压缩结果</returns>
  193. public static bool Zip(string fileToZip, string zipedFile, string password)
  194. {
  195. bool result = false;
  196. if (Directory.Exists(fileToZip))
  197. {
  198. result = ZipDirectory(fileToZip, zipedFile, password);
  199. }
  200. else if (File.Exists(fileToZip))
  201. {
  202. result = ZipFile(fileToZip, zipedFile, password);
  203. }
  204. return result;
  205. }
  206. /// <summary>
  207. /// 压缩文件或文件夹
  208. /// </summary>
  209. /// <param name="fileToZip">要压缩的路径</param>
  210. /// <param name="zipedFile">压缩后的文件名</param>
  211. /// <returns>压缩结果</returns>
  212. public static bool Zip(string fileToZip, string zipedFile)
  213. {
  214. bool result = Zip(fileToZip, zipedFile, null);
  215. return result;
  216. }
  217. #endregion
  218. #region 解压
  219. /// <summary>
  220. /// 解压功能(解压压缩文件到指定目录)
  221. /// </summary>
  222. /// <param name="fileToUnZip">待解压的文件</param>
  223. /// <param name="zipedFolder">指定解压目标目录</param>
  224. /// <param name="password">密码</param>
  225. /// <returns>解压结果</returns>
  226. public static bool UnZip(string fileToUnZip, string zipedFolder, string password)
  227. {
  228. bool result = true;
  229. FileStream fs = null;
  230. ZipInputStream zipStream = null;
  231. ZipEntry ent = null;
  232. string fileName;
  233. if (!File.Exists(fileToUnZip))
  234. {
  235. return false;
  236. }
  237. if (!Directory.Exists(zipedFolder))
  238. {
  239. Directory.CreateDirectory(zipedFolder);
  240. }
  241. try
  242. {
  243. zipStream = new ZipInputStream(File.OpenRead(fileToUnZip));
  244. if (!string.IsNullOrEmpty(password))
  245. {
  246. zipStream.Password = password;
  247. }
  248. while ((ent = zipStream.GetNextEntry()) != null)
  249. {
  250. if (!string.IsNullOrEmpty(ent.Name))
  251. {
  252. fileName = Path.Combine(zipedFolder, ent.Name);
  253. fileName = fileName.Replace('/', '\\');//change by Mr.HopeGi
  254. if (fileName.EndsWith("\\"))
  255. {
  256. Directory.CreateDirectory(fileName);
  257. continue;
  258. }
  259. fs = File.Create(fileName);
  260. int size = 2048;
  261. byte[] data = new byte[size];
  262. while (true)
  263. {
  264. size = zipStream.Read(data, 0, data.Length);
  265. if (size > 0)
  266. {
  267. fs.Write(data, 0, data.Length);
  268. }
  269. else
  270. {
  271. break;
  272. }
  273. }
  274. }
  275. }
  276. }
  277. catch
  278. {
  279. result = false;
  280. }
  281. finally
  282. {
  283. if (fs != null)
  284. {
  285. fs.Close();
  286. fs.Dispose();
  287. }
  288. if (zipStream != null)
  289. {
  290. zipStream.Close();
  291. zipStream.Dispose();
  292. }
  293. if (ent != null)
  294. {
  295. ent = null;
  296. }
  297. GC.Collect();
  298. GC.Collect(1);
  299. }
  300. return result;
  301. }
  302. /// <summary>
  303. /// 解压功能(解压压缩文件到指定目录)
  304. /// </summary>
  305. /// <param name="fileToUnZip">待解压的文件</param>
  306. /// <param name="zipedFolder">指定解压目标目录</param>
  307. /// <returns>解压结果</returns>
  308. public static bool UnZip(string fileToUnZip, string zipedFolder)
  309. {
  310. bool result = NewUnZip(fileToUnZip, zipedFolder, null, true);
  311. return result;
  312. }
  313. /// <summary>
  314. /// ZIP:解压一个zip文件
  315. /// </summary>
  316. /// <param name="ZipFile">需要解压的Zip文件(绝对路径)</param>
  317. /// <param name="TargetDirectory">解压到的目录</param>
  318. /// <param name="Password">解压密码</param>
  319. /// <param name="OverWrite">是否覆盖已存在的文件</param>
  320. public static bool NewUnZip(string ZipFile, string TargetDirectory, string Password, bool OverWrite = true)
  321. {
  322. try
  323. {
  324. //如果解压到的目录不存在,则报错
  325. if (!System.IO.Directory.Exists(TargetDirectory))
  326. {
  327. throw new System.IO.FileNotFoundException("指定的目录: " + TargetDirectory + " 不存在!");
  328. }
  329. //目录结尾
  330. if (!TargetDirectory.EndsWith("\\")) { TargetDirectory = TargetDirectory + "\\"; }
  331. using (ZipInputStream zipfiles = new ZipInputStream(File.OpenRead(ZipFile)))
  332. {
  333. zipfiles.Password = Password;
  334. ZipEntry theEntry;
  335. while ((theEntry = zipfiles.GetNextEntry()) != null)
  336. {
  337. string directoryName = "";
  338. string pathToZip = "";
  339. pathToZip = theEntry.Name;
  340. if (pathToZip != "")
  341. {
  342. directoryName = Path.GetDirectoryName(pathToZip) + "\\";
  343. }
  344. string fileName = Path.GetFileName(pathToZip);
  345. Directory.CreateDirectory(TargetDirectory + directoryName);
  346. if (fileName != "")
  347. {
  348. if ((File.Exists(TargetDirectory + directoryName + fileName) && OverWrite) || (!File.Exists(TargetDirectory + directoryName + fileName)))
  349. {
  350. try
  351. {
  352. using (FileStream streamWriter = File.Create(TargetDirectory + directoryName + fileName))
  353. {
  354. int size = 2048;
  355. byte[] data = new byte[2048];
  356. while (true)
  357. {
  358. size = zipfiles.Read(data, 0, data.Length);
  359. if (size > 0)
  360. {
  361. streamWriter.Write(data, 0, size);
  362. }
  363. else
  364. {
  365. break;
  366. }
  367. }
  368. streamWriter.Close();
  369. }
  370. }
  371. catch (Exception ex)
  372. {
  373. string message = ex.Message;
  374. //解压出错//若文件无损坏则可能为无法覆盖文件
  375. }
  376. }
  377. }
  378. }
  379. zipfiles.Close();
  380. }
  381. return true;
  382. }
  383. catch (Exception)
  384. {
  385. return false;
  386. }
  387. }
  388. #endregion
  389. #region 压缩文件
  390. /// <summary>
  391. /// 压缩文件
  392. /// </summary>
  393. /// <param name="fileNames">要打包的文件列表</param>
  394. /// <param name="GzipFileName">目标文件名</param>
  395. /// <param name="CompressionLevel">压缩品质级别(0~9)</param>
  396. /// <param name="deleteFile">是否删除原文件</param>
  397. public static void CompressFile(List<FileInfo> fileNames, string GzipFileName, int CompressionLevel, bool deleteFile)
  398. {
  399. ZipOutputStream s = new ZipOutputStream(File.Create(GzipFileName));
  400. try
  401. {
  402. s.SetLevel(CompressionLevel); //0 - store only to 9 - means best compression
  403. foreach (FileInfo file in fileNames)
  404. {
  405. FileStream fs = null;
  406. try
  407. {
  408. fs = file.Open(FileMode.Open, FileAccess.ReadWrite);
  409. }
  410. catch
  411. { continue; }
  412. // 方法二,将文件分批读入缓冲区
  413. byte[] data = new byte[2048];
  414. int size = 2048;
  415. ZipEntry entry = new ZipEntry(Path.GetFileName(file.Name))
  416. {
  417. DateTime = (file.CreationTime > file.LastWriteTime ? file.LastWriteTime : file.CreationTime)
  418. };
  419. s.PutNextEntry(entry);
  420. while (true)
  421. {
  422. size = fs.Read(data, 0, size);
  423. if (size <= 0)
  424. {
  425. break;
  426. }
  427. s.Write(data, 0, size);
  428. }
  429. fs.Close();
  430. if (deleteFile)
  431. {
  432. file.Delete();
  433. }
  434. }
  435. }
  436. finally
  437. {
  438. s.Finish();
  439. s.Close();
  440. }
  441. }
  442. public static void CompressFile(string fileName, string GzipFileName, int CompressionLevel, bool deleteFile)
  443. {
  444. ZipOutputStream s = new ZipOutputStream(File.Create(GzipFileName));
  445. try
  446. {
  447. s.SetLevel(CompressionLevel); //0 - store only to 9 - means best compression
  448. FileInfo file = new FileInfo(fileName);
  449. FileStream fs = null;
  450. try
  451. {
  452. fs = file.Open(FileMode.Open, FileAccess.ReadWrite);
  453. }
  454. catch
  455. { return; }
  456. // 方法二,将文件分批读入缓冲区
  457. byte[] data = new byte[2048];
  458. int size = 2048;
  459. ZipEntry entry = new ZipEntry(Path.GetFileName(file.Name))
  460. {
  461. DateTime = (file.CreationTime > file.LastWriteTime ? file.LastWriteTime : file.CreationTime)
  462. };
  463. s.PutNextEntry(entry);
  464. while (true)
  465. {
  466. size = fs.Read(data, 0, size);
  467. if (size <= 0)
  468. {
  469. break;
  470. }
  471. s.Write(data, 0, size);
  472. }
  473. fs.Close();
  474. if (deleteFile)
  475. {
  476. file.Delete();
  477. }
  478. }
  479. finally
  480. {
  481. s.Finish();
  482. s.Close();
  483. }
  484. }
  485. /// <summary>
  486. /// 压缩文件夹
  487. /// </summary>
  488. /// <param name="dirPath">要打包的文件夹</param>
  489. /// <param name="GzipFileName">目标文件名</param>
  490. /// <param name="CompressionLevel">压缩品质级别(0~9)</param>
  491. /// <param name="deleteDir">是否删除原文件夹</param>
  492. public static void CompressDirectory(string dirPath, string GzipFileName, int CompressionLevel, bool deleteDir)
  493. {
  494. //压缩文件为空时默认与压缩文件夹同一级目录
  495. if (GzipFileName == string.Empty)
  496. {
  497. GzipFileName = dirPath.Substring(dirPath.LastIndexOf("//") + 1);
  498. GzipFileName = dirPath.Substring(0, dirPath.LastIndexOf("//")) + "//" + GzipFileName + ".zip";
  499. }
  500. //if (Path.GetExtension(GzipFileName) != ".zip")
  501. //{
  502. // GzipFileName = GzipFileName + ".zip";
  503. //}
  504. using (ZipOutputStream zipoutputstream = new ZipOutputStream(File.Create(GzipFileName)))
  505. {
  506. zipoutputstream.SetLevel(CompressionLevel);
  507. Crc32 crc = new Crc32();
  508. Dictionary<string, DateTime> fileList = GetAllFies(dirPath);
  509. foreach (KeyValuePair<string, DateTime> item in fileList)
  510. {
  511. FileStream fs = File.OpenRead(item.Key.ToString());
  512. byte[] buffer = new byte[fs.Length];
  513. fs.Read(buffer, 0, buffer.Length);
  514. ZipEntry entry = new ZipEntry(item.Key.Substring(dirPath.Length))
  515. {
  516. DateTime = item.Value,
  517. Size = fs.Length
  518. };
  519. fs.Close();
  520. crc.Reset();
  521. crc.Update(buffer);
  522. entry.Crc = crc.Value;
  523. zipoutputstream.PutNextEntry(entry);
  524. zipoutputstream.Write(buffer, 0, buffer.Length);
  525. }
  526. }
  527. if (deleteDir)
  528. {
  529. Directory.Delete(dirPath, true);
  530. }
  531. }
  532. /// <summary>
  533. /// 获取所有文件
  534. /// </summary>
  535. /// <returns></returns>
  536. private static Dictionary<string, DateTime> GetAllFies(string dir)
  537. {
  538. Dictionary<string, DateTime> FilesList = new Dictionary<string, DateTime>();
  539. DirectoryInfo fileDire = new DirectoryInfo(dir);
  540. if (!fileDire.Exists)
  541. {
  542. throw new System.IO.FileNotFoundException("目录:" + fileDire.FullName + "没有找到!");
  543. }
  544. GetAllDirFiles(fileDire, FilesList);
  545. GetAllDirsFiles(fileDire.GetDirectories(), FilesList);
  546. return FilesList;
  547. }
  548. /// <summary>
  549. /// 获取一个文件夹下的所有文件夹里的文件
  550. /// </summary>
  551. /// <param name="dirs"></param>
  552. /// <param name="filesList"></param>
  553. private static void GetAllDirsFiles(DirectoryInfo[] dirs, Dictionary<string, DateTime> filesList)
  554. {
  555. foreach (DirectoryInfo dir in dirs)
  556. {
  557. foreach (FileInfo file in dir.GetFiles("*.*"))
  558. {
  559. filesList.Add(file.FullName, file.LastWriteTime);
  560. }
  561. GetAllDirsFiles(dir.GetDirectories(), filesList);
  562. }
  563. }
  564. /// <summary>
  565. /// 获取一个文件夹下的文件
  566. /// </summary>
  567. /// <param name="dir">目录名称</param>
  568. /// <param name="filesList">文件列表HastTable</param>
  569. private static void GetAllDirFiles(DirectoryInfo dir, Dictionary<string, DateTime> filesList)
  570. {
  571. foreach (FileInfo file in dir.GetFiles("*.*"))
  572. {
  573. filesList.Add(file.FullName, file.LastWriteTime);
  574. }
  575. }
  576. #endregion
  577. #region 解压缩文件
  578. /// <summary>
  579. /// 解压缩文件
  580. /// </summary>
  581. /// <param name="GzipFile">压缩包文件名</param>
  582. /// <param name="targetPath">解压缩目标路径</param>
  583. public static void Decompress(string GzipFile, string targetPath)
  584. {
  585. //string directoryName = Path.GetDirectoryName(targetPath + "//") + "//";
  586. string directoryName = targetPath;
  587. if (!Directory.Exists(directoryName))
  588. {
  589. Directory.CreateDirectory(directoryName);//生成解压目录
  590. }
  591. string CurrentDirectory = directoryName;
  592. byte[] data = new byte[2048];
  593. int size = 2048;
  594. ZipEntry theEntry = null;
  595. using (ZipInputStream s = new ZipInputStream(File.OpenRead(GzipFile)))
  596. {
  597. while ((theEntry = s.GetNextEntry()) != null)
  598. {
  599. if (theEntry.IsDirectory)
  600. {// 该结点是目录
  601. if (!Directory.Exists(CurrentDirectory + theEntry.Name))
  602. {
  603. Directory.CreateDirectory(CurrentDirectory + theEntry.Name);
  604. }
  605. }
  606. else
  607. {
  608. if (theEntry.Name != string.Empty)
  609. {
  610. // 检查多级目录是否存在
  611. if (theEntry.Name.Contains("\\"))
  612. {
  613. string parentDirPath = theEntry.Name.Remove(theEntry.Name.LastIndexOf("\\") + 1);
  614. if (!Directory.Exists(parentDirPath))
  615. {
  616. Directory.CreateDirectory(CurrentDirectory + parentDirPath);
  617. }
  618. }
  619. //解压文件到指定的目录
  620. using (FileStream streamWriter = File.Create(CurrentDirectory + theEntry.Name))
  621. {
  622. while (true)
  623. {
  624. size = s.Read(data, 0, data.Length);
  625. if (size <= 0)
  626. {
  627. break;
  628. }
  629. streamWriter.Write(data, 0, size);
  630. }
  631. streamWriter.Close();
  632. }
  633. }
  634. }
  635. }
  636. s.Close();
  637. }
  638. }
  639. #endregion
  640. }
  641. }