• 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
     
  • 相关阅读:
    值初始化-new
    CLI-error
    批量处理
    makefile --文件文档经链接使用
    数据库查询优化
    动态加载数据抓取-Ajax
    requests.post()
    requests.get()参数
    xpath练习(链家二手房案例,百度贴吧图片抓取案例)
    xpath解析.lxml解析库
  • 原文地址:https://www.cnblogs.com/conexpress/p/SharpZipClass.html
Copyright © 2020-2023  润新知