C#壓縮庫SharpZipLib的應用


   SharpZipLib是一個開源的C#壓縮解壓庫,應用非常廣泛。就像用ADO.NET操作數據庫要打開連接、執行命令、關閉連接等多個步驟一樣,用SharpZipLib進行壓縮和解壓也需要多個步驟。除了初學者會用原始的方法做一步一步完成,實際開發的時候都會進行更易用的封裝。這里分享我對SharpZipLib的封裝,支持對文件和字節進行壓縮和解壓操作,支持多個文件和文件夾壓縮,支持設置備注和密碼。(文章源網址:http://www.cnblogs.com/conexpress/p/SharpZipClass.html)
    SharpZipLib的官方地址是:http://icsharpcode.github.io/SharpZipLib/,實際使用可以通過NuGet獲取,在NuGet的地址是:http://www.nuget.org/packages/SharpZipLib/
SharpZipLib_NuGet
 
在Visual Studio中可以通過NuGet程序包管理控制台輸入命令PM> Install-Package SharpZipLib或者用NuGet管理界面搜索並安裝。
我把使用SharpZipLib的方法卸載一個類里面,作為靜態方法調用,免去創建類的麻煩。其中核心壓縮和解壓文件的方法代碼如下:
  1         /// <summary>
  2         /// 壓縮多個文件/文件夾
  3         /// </summary>
  4         /// <param name="sourceList">源文件/文件夾路徑列表</param>
  5         /// <param name="zipFilePath">壓縮文件路徑</param>
  6         /// <param name="comment">注釋信息</param>
  7         /// <param name="password">壓縮密碼</param>
  8         /// <param name="compressionLevel">壓縮等級,范圍從0到9,可選,默認為6</param>
  9         /// <returns></returns>
 10         public static bool CompressFile(IEnumerable<string> sourceList, string zipFilePath,
 11              string comment = null, string password = null, int compressionLevel = 6)
 12         {
 13             bool result = false;
 14 
 15             try
 16             {
 17                 //檢測目標文件所屬的文件夾是否存在,如果不存在則建立
 18                 string zipFileDirectory = Path.GetDirectoryName(zipFilePath);
 19                 if (!Directory.Exists(zipFileDirectory))
 20                 {
 21                     Directory.CreateDirectory(zipFileDirectory);
 22                 }
 23 
 24                 Dictionary<string, string> dictionaryList = PrepareFileSystementities(sourceList);
 25 
 26                 using (ZipOutputStream zipStream = new ZipOutputStream(File.Create(zipFilePath)))
 27                 {
 28                     zipStream.Password = password;//設置密碼
 29                     zipStream.SetComment(comment);//添加注釋
 30                     zipStream.SetLevel(CheckCompressionLevel(compressionLevel));//設置壓縮等級
 31 
 32                     foreach (string key in dictionaryList.Keys)//從字典取文件添加到壓縮文件
 33                     {
 34                         if (File.Exists(key))//判斷是文件還是文件夾
 35                         {
 36                             FileInfo fileItem = new FileInfo(key);
 37 
 38                             using (FileStream readStream = fileItem.Open(FileMode.Open,
 39                                 FileAccess.Read, FileShare.Read))
 40                             {
 41                                 ZipEntry zipEntry = new ZipEntry(dictionaryList[key]);
 42                                 zipEntry.DateTime = fileItem.LastWriteTime;
 43                                 zipEntry.Size = readStream.Length;
 44                                 zipStream.PutNextEntry(zipEntry);
 45                                 int readLength = 0;
 46                                 byte[] buffer = new byte[BufferSize];
 47 
 48                                 do
 49                                 {
 50                                     readLength = readStream.Read(buffer, 0, BufferSize);
 51                                     zipStream.Write(buffer, 0, readLength);
 52                                 } while (readLength == BufferSize);
 53 
 54                                 readStream.Close();
 55                             }
 56                         }
 57                         else//對文件夾的處理
 58                         {
 59                             ZipEntry zipEntry = new ZipEntry(dictionaryList[key] + "/");
 60                             zipStream.PutNextEntry(zipEntry);
 61                         }
 62                     }
 63 
 64                     zipStream.Flush();
 65                     zipStream.Finish();
 66                     zipStream.Close();
 67                 }
 68 
 69                 result = true;
 70             }
 71             catch (System.Exception ex)
 72             {
 73                 throw new Exception("壓縮文件失敗", ex);
 74             }
 75 
 76             return result;
 77         }
 78 
 79         /// <summary>
 80         /// 解壓文件到指定文件夾
 81         /// </summary>
 82         /// <param name="sourceFile">壓縮文件</param>
 83         /// <param name="destinationDirectory">目標文件夾,如果為空則解壓到當前文件夾下</param>
 84         /// <param name="password">密碼</param>
 85         /// <returns></returns>
 86         public static bool DecomparessFile(string sourceFile, string destinationDirectory = null, string password = null)
 87         {
 88             bool result = false;
 89 
 90             if (!File.Exists(sourceFile))
 91             {
 92                 throw new FileNotFoundException("要解壓的文件不存在", sourceFile);
 93             }
 94 
 95             if (string.IsNullOrWhiteSpace(destinationDirectory))
 96             {
 97                 destinationDirectory = Path.GetDirectoryName(sourceFile);
 98             }
 99 
100             try
101             {
102                 if (!Directory.Exists(destinationDirectory))
103                 {
104                     Directory.CreateDirectory(destinationDirectory);
105                 }
106 
107                 using (ZipInputStream zipStream = new ZipInputStream(File.Open(sourceFile, FileMode.Open,
108                     FileAccess.Read, FileShare.Read)))
109                 {
110                     zipStream.Password = password;
111                     ZipEntry zipEntry = zipStream.GetNextEntry();
112 
113                     while (zipEntry != null)
114                     {
115                         if (zipEntry.IsDirectory)//如果是文件夾則創建
116                         {
117                             Directory.CreateDirectory(Path.Combine(destinationDirectory,
118                                 Path.GetDirectoryName(zipEntry.Name)));
119                         }
120                         else
121                         {
122                             string fileName = Path.GetFileName(zipEntry.Name);
123                             if (!string.IsNullOrEmpty(fileName) && fileName.Trim().Length > 0)
124                             {
125                                 FileInfo fileItem = new FileInfo(Path.Combine(destinationDirectory, zipEntry.Name));
126                                 using (FileStream writeStream = fileItem.Create())
127                                 {
128                                     byte[] buffer = new byte[BufferSize];
129                                     int readLength = 0;
130 
131                                     do
132                                     {
133                                         readLength = zipStream.Read(buffer, 0, BufferSize);
134                                         writeStream.Write(buffer, 0, readLength);
135                                     } while (readLength == BufferSize);
136 
137                                     writeStream.Flush();
138                                     writeStream.Close();
139                                 }
140                                 fileItem.LastWriteTime = zipEntry.DateTime;
141                             }
142                         }
143                         zipEntry = zipStream.GetNextEntry();//獲取下一個文件
144                     }
145 
146                     zipStream.Close();
147                 }
148                 result = true;
149             }
150             catch (System.Exception ex)
151             {
152                 throw new Exception("文件解壓發生錯誤", ex);
153             }
154 
155             return result;
156         }
壓縮方法CompressFile中sourceList是路徑數組,支持文件夾和文件的路徑。當遇到文件夾時會自動將下級文件和文件夾包含,並會檢測重復項。文件路徑處理的方法如下:
 1         /// <summary>
 2         /// 為壓縮准備文件系統對象
 3         /// </summary>
 4         /// <param name="sourceFileEntityPathList"></param>
 5         /// <returns></returns>
 6         private static Dictionary<string, string> PrepareFileSystementities(IEnumerable<string> sourceFileEntityPathList)
 7         {
 8             Dictionary<string, string> fileEntityDictionary = new Dictionary<string, string>();//文件字典
 9             string parentDirectoryPath = "";
10             foreach (string fileEntityPath in sourceFileEntityPathList)
11             {
12                 string path = fileEntityPath;
13                 //保證傳入的文件夾也被壓縮進文件
14                 if (path.EndsWith(@"\"))
15                 {
16                     path = path.Remove(path.LastIndexOf(@"\"));
17                 }
18 
19                 parentDirectoryPath = Path.GetDirectoryName(path) + @"\";
20 
21                 if (parentDirectoryPath.EndsWith(@":\\"))//防止根目錄下把盤符壓入的錯誤
22                 {
23                     parentDirectoryPath = parentDirectoryPath.Replace(@"\\", @"\");
24                 }
25 
26                 //獲取目錄中所有的文件系統對象
27                 Dictionary<string, string> subDictionary = GetAllFileSystemEntities(path, parentDirectoryPath);
28 
29                 //將文件系統對象添加到總的文件字典中
30                 foreach (string key in subDictionary.Keys)
31                 {
32                     if (!fileEntityDictionary.ContainsKey(key))//檢測重復項
33                     {
34                         fileEntityDictionary.Add(key, subDictionary[key]);
35                     }
36                 }
37             }
38             return fileEntityDictionary;
39         }
40 
41         /// <summary>
42         /// 獲取所有文件系統對象
43         /// </summary>
44         /// <param name="source">源路徑</param>
45         /// <param name="topDirectory">頂級文件夾</param>
46         /// <returns>字典中Key為完整路徑,Value為文件(夾)名稱</returns>
47         private static Dictionary<string, string> GetAllFileSystemEntities(string source, string topDirectory)
48         {
49             Dictionary<string, string> entitiesDictionary = new Dictionary<string, string>();
50             entitiesDictionary.Add(source, source.Replace(topDirectory, ""));
51 
52             if (Directory.Exists(source))
53             {
54                 //一次性獲取下級所有目錄,避免遞歸
55                 string[] directories = Directory.GetDirectories(source, "*.*", SearchOption.AllDirectories);
56                 foreach (string directory in directories)
57                 {
58                     entitiesDictionary.Add(directory, directory.Replace(topDirectory, ""));
59                 }
60 
61                 string[] files = Directory.GetFiles(source, "*.*", SearchOption.AllDirectories);
62                 foreach (string file in files)
63                 {
64                     entitiesDictionary.Add(file, file.Replace(topDirectory, ""));
65                 }
66             }
67 
68             return entitiesDictionary;
69         }

除了支持文件和文件夾壓縮解壓,還提供了對字節的壓縮解壓方法:

  1         /// <summary>
  2         /// 壓縮字節數組
  3         /// </summary>
  4         /// <param name="sourceBytes">源字節數組</param>
  5         /// <param name="compressionLevel">壓縮等級</param>
  6         /// <param name="password">密碼</param>
  7         /// <returns>壓縮后的字節數組</returns>
  8         public static byte[] CompressBytes(byte[] sourceBytes, string password = null, int compressionLevel = 6)
  9         {
 10             byte[] result = new byte[] { };
 11 
 12             if (sourceBytes.Length > 0)
 13             {
 14                 try
 15                 {
 16                     using (MemoryStream tempStream = new MemoryStream())
 17                     {
 18                         using (MemoryStream readStream = new MemoryStream(sourceBytes))
 19                         {
 20                             using (ZipOutputStream zipStream = new ZipOutputStream(tempStream))
 21                             {
 22                                 zipStream.Password = password;//設置密碼
 23                                 zipStream.SetLevel(CheckCompressionLevel(compressionLevel));//設置壓縮等級
 24 
 25                                 ZipEntry zipEntry = new ZipEntry("ZipBytes");
 26                                 zipEntry.DateTime = DateTime.Now;
 27                                 zipEntry.Size = sourceBytes.Length;
 28                                 zipStream.PutNextEntry(zipEntry);
 29                                 int readLength = 0;
 30                                 byte[] buffer = new byte[BufferSize];
 31 
 32                                 do
 33                                 {
 34                                     readLength = readStream.Read(buffer, 0, BufferSize);
 35                                     zipStream.Write(buffer, 0, readLength);
 36                                 } while (readLength == BufferSize);
 37 
 38                                 readStream.Close();
 39                                 zipStream.Flush();
 40                                 zipStream.Finish();
 41                                 result = tempStream.ToArray();
 42                                 zipStream.Close();
 43                             }
 44                         }
 45                     }
 46                 }
 47                 catch (System.Exception ex)
 48                 {
 49                     throw new Exception("壓縮字節數組發生錯誤", ex);
 50                 }
 51             }
 52 
 53             return result;
 54         }
 55 
 56         /// <summary>
 57         /// 解壓字節數組
 58         /// </summary>
 59         /// <param name="sourceBytes">源字節數組</param>
 60         /// <param name="password">密碼</param>
 61         /// <returns>解壓后的字節數組</returns>
 62         public static byte[] DecompressBytes(byte[] sourceBytes, string password = null)
 63         {
 64             byte[] result = new byte[] { };
 65 
 66             if (sourceBytes.Length > 0)
 67             {
 68                 try
 69                 {
 70                     using (MemoryStream tempStream = new MemoryStream(sourceBytes))
 71                     {
 72                         using (MemoryStream writeStream = new MemoryStream())
 73                         {
 74                             using (ZipInputStream zipStream = new ZipInputStream(tempStream))
 75                             {
 76                                 zipStream.Password = password;
 77                                 ZipEntry zipEntry = zipStream.GetNextEntry();
 78 
 79                                 if (zipEntry != null)
 80                                 {
 81                                     byte[] buffer = new byte[BufferSize];
 82                                     int readLength = 0;
 83 
 84                                     do
 85                                     {
 86                                         readLength = zipStream.Read(buffer, 0, BufferSize);
 87                                         writeStream.Write(buffer, 0, readLength);
 88                                     } while (readLength == BufferSize);
 89 
 90                                     writeStream.Flush();
 91                                     result = writeStream.ToArray();
 92                                     writeStream.Close();
 93                                 }
 94                                 zipStream.Close();
 95                             }
 96                         }
 97                     }
 98                 }
 99                 catch (System.Exception ex)
100                 {
101                     throw new Exception("解壓字節數組發生錯誤", ex);
102                 }
103             }
104             return result;
105         }
View Code

為了測試該類,我寫了一個WinForm程序,界面如下:

SharpZipLib測試界面
可以將文件和文件夾拖放到壓縮列表中,選中壓縮列表中的對象可以按Delete鍵進行刪除。文件解壓區域也可以將要解壓的文件拖放到文件路徑輸入文本框。實際測試可以正確壓縮和解壓,包括設置密碼,壓縮和解壓操作和WinRAR完全兼容。如果您在代碼中發現問題或有可以優化完善的地方,歡迎指出,謝謝!
程序源代碼下載:http://files.cnblogs.com/files/conexpress/SharpZipTest.zip
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM