C#中關於zip壓縮解壓協助類的封裝
之前一個同學問了這個問題後,看了園子裡其它園友的封裝,都很零碎,調用也不是很方便。所以自己就封裝了一個zip解壓的類。後來想整理下怕自己忘了。就把壓縮的類也一併封裝了。
c#下壓縮解壓,主要是用第三方類庫進行封裝的。ICSharpCode.SharpZipLib.dll類庫,連結地址為你官方下載連結。壓縮主要是用流的方式進行壓縮的。
壓縮檔及檔案夾。檔案壓縮很簡單,把待壓縮的檔案用流的方式讀到記憶體中,然後放到壓縮流中。就可以了。檔案夾就稍微麻煩下了。因為要把待壓縮的檔案夾解壓後保留檔案夾檔案的階層。所以我的實現方式就是 遞迴遍曆檔案夾中的檔案。計算其相對位置放到壓縮流中。
代碼如下
/// <summary> /// 壓縮檔或者檔案夾 /// </summary> /// <param name="_depositPath">壓縮後檔案的存放路徑 如C:\\windows\abc.zip</param> /// <returns></returns> public bool CompressionZip(string _depositPath) { bool result = true; FileStream fs = null; try { ZipOutputStream ComStream = new ZipOutputStream(File.Create(_depositPath)); ComStream.SetLevel(9); //壓縮等級 foreach (string path in AbsolutePaths) { //如果是目錄 if (Directory.Exists(path)) { ZipFloder(path, ComStream, path); } else if (File.Exists(path))//如果是檔案 { fs = File.OpenRead(path); byte[] bts = new byte[fs.Length]; fs.Read(bts, 0, bts.Length); ZipEntry ze = new ZipEntry(new FileInfo(path).Name); ComStream.PutNextEntry(ze); //為壓縮檔流提供一個容器 ComStream.Write(bts, 0, bts.Length); //寫入位元組 } } ComStream.Finish(); // 結束壓縮 ComStream.Close(); } catch (Exception ex) { if (fs != null) { fs.Close(); } errorMsg = ex.Message; result = false; } return result; } //壓縮檔夾 private void ZipFloder(string _OfloderPath, ZipOutputStream zos, string _floderPath) { foreach (FileSystemInfo item in new DirectoryInfo(_floderPath).GetFileSystemInfos()) { if (Directory.Exists(item.FullName)) { ZipFloder(_OfloderPath, zos, item.FullName); } else if (File.Exists(item.FullName))//如果是檔案 { DirectoryInfo ODir = new DirectoryInfo(_OfloderPath); string fullName2 = new FileInfo(item.FullName).FullName; string path = ODir.Name + fullName2.Substring(ODir.FullName.Length, fullName2.Length - ODir.FullName.Length);//擷取相對目錄 FileStream fs = File.OpenRead(fullName2); byte[] bts = new byte[fs.Length]; fs.Read(bts, 0, bts.Length); ZipEntry ze = new ZipEntry(path); zos.PutNextEntry(ze); //為壓縮檔流提供一個容器 zos.Write(bts, 0, bts.Length); //寫入位元組 } } }
關於解壓 解壓就簡單多了。有檔案解壓檔案,有檔案夾 遍曆,解壓其中的檔案。解壓的檔案中已經包含了其與檔案夾的層次關係。
/// <summary> /// 解壓 /// </summary> /// <param name="_depositPath">壓縮檔路徑</param> /// <param name="_floderPath">解壓的路徑</param> /// <returns></returns> public bool DeCompressionZip(string _depositPath, string _floderPath) { bool result = true; FileStream fs=null; try { ZipInputStream InpStream = new ZipInputStream(File.OpenRead(_depositPath)); ZipEntry ze = InpStream.GetNextEntry();//擷取壓縮檔中的每一個檔案 Directory.CreateDirectory(_floderPath);//建立解壓檔案夾 while (ze != null)//如果解壓完ze則是null { if (ze.IsFile)//壓縮zipINputStream裡面存的都是檔案。帶檔案夾的檔案名稱字是檔案夾\\檔案名稱 { string[] strs=ze.Name.Split('\\');//如果檔案名稱中包含’\\‘則表明有檔案夾 if (strs.Length > 1) { //兩層迴圈用於一層一層建立檔案夾 for (int i = 0; i < strs.Length-1; i++) { string floderPath=_floderPath; for (int j = 0; j < i; j++) { floderPath = floderPath + "\\" + strs[j]; } floderPath=floderPath+"\\"+strs[i]; Directory.CreateDirectory(floderPath); } } fs = new FileStream(_floderPath+"\\"+ze.Name, FileMode.OpenOrCreate, FileAccess.Write);//建立檔案 //迴圈讀取檔案到檔案流中 while (true) { byte[] bts = new byte[1024]; int i= InpStream.Read(bts, 0, bts.Length); if (i > 0) { fs.Write(bts, 0, i); } else { fs.Flush(); fs.Close(); break; } } } ze = InpStream.GetNextEntry(); } } catch (Exception ex) { if (fs != null) { fs.Close(); } errorMsg = ex.Message; result = false; } return result; }
最後做個總結。C#作為進階語言,其強大的類庫和第三方提供的類庫。可以做很多事情。但也有弊端,用第三方類庫效能不是很高。我壓縮幾百M的東西。cpu瞬間跑到50%多。比360壓縮和zip壓縮效能差遠了。所以此類也就適用壓縮比較小的東西。
完整例子