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/
 
在Visual Studio中可以通过NuGet程序包管理控制台输入命令PM> Install-Package SharpZipLib或者用NuGet管理界面搜索并安装。
我把使用SharpZipLib的方法卸载一个类里面,作为静态方法调用,免去创建类的麻烦。其中核心压缩和解压文件的方法代码如下:
         /// <summary>
/// 压缩多个文件/文件夹
/// </summary>
/// <param name="sourceList">源文件/文件夹路径列表</param>
/// <param name="zipFilePath">压缩文件路径</param>
/// <param name="comment">注释信息</param>
/// <param name="password">压缩密码</param>
/// <param name="compressionLevel">压缩等级,范围从0到9,可选,默认为6</param>
/// <returns></returns>
public static bool CompressFile(IEnumerable<string> sourceList, string zipFilePath,
string comment = null, string password = null, int compressionLevel = )
{
bool result = false; try
{
//检测目标文件所属的文件夹是否存在,如果不存在则建立
string zipFileDirectory = Path.GetDirectoryName(zipFilePath);
if (!Directory.Exists(zipFileDirectory))
{
Directory.CreateDirectory(zipFileDirectory);
} Dictionary<string, string> dictionaryList = PrepareFileSystementities(sourceList); using (ZipOutputStream zipStream = new ZipOutputStream(File.Create(zipFilePath)))
{
zipStream.Password = password;//设置密码
zipStream.SetComment(comment);//添加注释
zipStream.SetLevel(CheckCompressionLevel(compressionLevel));//设置压缩等级 foreach (string key in dictionaryList.Keys)//从字典取文件添加到压缩文件
{
if (File.Exists(key))//判断是文件还是文件夹
{
FileInfo fileItem = new FileInfo(key); using (FileStream readStream = fileItem.Open(FileMode.Open,
FileAccess.Read, FileShare.Read))
{
ZipEntry zipEntry = new ZipEntry(dictionaryList[key]);
zipEntry.DateTime = fileItem.LastWriteTime;
zipEntry.Size = readStream.Length;
zipStream.PutNextEntry(zipEntry);
int readLength = ;
byte[] buffer = new byte[BufferSize]; do
{
readLength = readStream.Read(buffer, , BufferSize);
zipStream.Write(buffer, , readLength);
} while (readLength == BufferSize); readStream.Close();
}
}
else//对文件夹的处理
{
ZipEntry zipEntry = new ZipEntry(dictionaryList[key] + "/");
zipStream.PutNextEntry(zipEntry);
}
} zipStream.Flush();
zipStream.Finish();
zipStream.Close();
} result = true;
}
catch (System.Exception ex)
{
throw new Exception("压缩文件失败", ex);
} return result;
} /// <summary>
/// 解压文件到指定文件夹
/// </summary>
/// <param name="sourceFile">压缩文件</param>
/// <param name="destinationDirectory">目标文件夹,如果为空则解压到当前文件夹下</param>
/// <param name="password">密码</param>
/// <returns></returns>
public static bool DecomparessFile(string sourceFile, string destinationDirectory = null, string password = null)
{
bool result = false; if (!File.Exists(sourceFile))
{
throw new FileNotFoundException("要解压的文件不存在", sourceFile);
} if (string.IsNullOrWhiteSpace(destinationDirectory))
{
destinationDirectory = Path.GetDirectoryName(sourceFile);
} try
{
if (!Directory.Exists(destinationDirectory))
{
Directory.CreateDirectory(destinationDirectory);
} using (ZipInputStream zipStream = new ZipInputStream(File.Open(sourceFile, FileMode.Open,
FileAccess.Read, FileShare.Read)))
{
zipStream.Password = password;
ZipEntry zipEntry = zipStream.GetNextEntry(); while (zipEntry != null)
{
if (zipEntry.IsDirectory)//如果是文件夹则创建
{
Directory.CreateDirectory(Path.Combine(destinationDirectory,
Path.GetDirectoryName(zipEntry.Name)));
}
else
{
string fileName = Path.GetFileName(zipEntry.Name);
if (!string.IsNullOrEmpty(fileName) && fileName.Trim().Length > )
{
FileInfo fileItem = new FileInfo(Path.Combine(destinationDirectory, zipEntry.Name));
using (FileStream writeStream = fileItem.Create())
{
byte[] buffer = new byte[BufferSize];
int readLength = ; do
{
readLength = zipStream.Read(buffer, , BufferSize);
writeStream.Write(buffer, , readLength);
} while (readLength == BufferSize); writeStream.Flush();
writeStream.Close();
}
fileItem.LastWriteTime = zipEntry.DateTime;
}
}
zipEntry = zipStream.GetNextEntry();//获取下一个文件
} zipStream.Close();
}
result = true;
}
catch (System.Exception ex)
{
throw new Exception("文件解压发生错误", ex);
} return result;
}
压缩方法CompressFile中sourceList是路径数组,支持文件夹和文件的路径。当遇到文件夹时会自动将下级文件和文件夹包含,并会检测重复项。文件路径处理的方法如下:
         /// <summary>
/// 为压缩准备文件系统对象
/// </summary>
/// <param name="sourceFileEntityPathList"></param>
/// <returns></returns>
private static Dictionary<string, string> PrepareFileSystementities(IEnumerable<string> sourceFileEntityPathList)
{
Dictionary<string, string> fileEntityDictionary = new Dictionary<string, string>();//文件字典
string parentDirectoryPath = "";
foreach (string fileEntityPath in sourceFileEntityPathList)
{
string path = fileEntityPath;
//保证传入的文件夹也被压缩进文件
if (path.EndsWith(@"\"))
{
path = path.Remove(path.LastIndexOf(@"\"));
} parentDirectoryPath = Path.GetDirectoryName(path) + @"\"; if (parentDirectoryPath.EndsWith(@":\\"))//防止根目录下把盘符压入的错误
{
parentDirectoryPath = parentDirectoryPath.Replace(@"\\", @"\");
} //获取目录中所有的文件系统对象
Dictionary<string, string> subDictionary = GetAllFileSystemEntities(path, parentDirectoryPath); //将文件系统对象添加到总的文件字典中
foreach (string key in subDictionary.Keys)
{
if (!fileEntityDictionary.ContainsKey(key))//检测重复项
{
fileEntityDictionary.Add(key, subDictionary[key]);
}
}
}
return fileEntityDictionary;
} /// <summary>
/// 获取所有文件系统对象
/// </summary>
/// <param name="source">源路径</param>
/// <param name="topDirectory">顶级文件夹</param>
/// <returns>字典中Key为完整路径,Value为文件(夹)名称</returns>
private static Dictionary<string, string> GetAllFileSystemEntities(string source, string topDirectory)
{
Dictionary<string, string> entitiesDictionary = new Dictionary<string, string>();
entitiesDictionary.Add(source, source.Replace(topDirectory, "")); if (Directory.Exists(source))
{
//一次性获取下级所有目录,避免递归
string[] directories = Directory.GetDirectories(source, "*.*", SearchOption.AllDirectories);
foreach (string directory in directories)
{
entitiesDictionary.Add(directory, directory.Replace(topDirectory, ""));
} string[] files = Directory.GetFiles(source, "*.*", SearchOption.AllDirectories);
foreach (string file in files)
{
entitiesDictionary.Add(file, file.Replace(topDirectory, ""));
}
} return entitiesDictionary;
}

除了支持文件和文件夹压缩解压,还提供了对字节的压缩解压方法:

         /// <summary>
/// 压缩字节数组
/// </summary>
/// <param name="sourceBytes">源字节数组</param>
/// <param name="compressionLevel">压缩等级</param>
/// <param name="password">密码</param>
/// <returns>压缩后的字节数组</returns>
public static byte[] CompressBytes(byte[] sourceBytes, string password = null, int compressionLevel = )
{
byte[] result = new byte[] { }; if (sourceBytes.Length > )
{
try
{
using (MemoryStream tempStream = new MemoryStream())
{
using (MemoryStream readStream = new MemoryStream(sourceBytes))
{
using (ZipOutputStream zipStream = new ZipOutputStream(tempStream))
{
zipStream.Password = password;//设置密码
zipStream.SetLevel(CheckCompressionLevel(compressionLevel));//设置压缩等级 ZipEntry zipEntry = new ZipEntry("ZipBytes");
zipEntry.DateTime = DateTime.Now;
zipEntry.Size = sourceBytes.Length;
zipStream.PutNextEntry(zipEntry);
int readLength = ;
byte[] buffer = new byte[BufferSize]; do
{
readLength = readStream.Read(buffer, , BufferSize);
zipStream.Write(buffer, , readLength);
} while (readLength == BufferSize); readStream.Close();
zipStream.Flush();
zipStream.Finish();
result = tempStream.ToArray();
zipStream.Close();
}
}
}
}
catch (System.Exception ex)
{
throw new Exception("压缩字节数组发生错误", ex);
}
} return result;
} /// <summary>
/// 解压字节数组
/// </summary>
/// <param name="sourceBytes">源字节数组</param>
/// <param name="password">密码</param>
/// <returns>解压后的字节数组</returns>
public static byte[] DecompressBytes(byte[] sourceBytes, string password = null)
{
byte[] result = new byte[] { }; if (sourceBytes.Length > )
{
try
{
using (MemoryStream tempStream = new MemoryStream(sourceBytes))
{
using (MemoryStream writeStream = new MemoryStream())
{
using (ZipInputStream zipStream = new ZipInputStream(tempStream))
{
zipStream.Password = password;
ZipEntry zipEntry = zipStream.GetNextEntry(); if (zipEntry != null)
{
byte[] buffer = new byte[BufferSize];
int readLength = ; do
{
readLength = zipStream.Read(buffer, , BufferSize);
writeStream.Write(buffer, , readLength);
} while (readLength == BufferSize); writeStream.Flush();
result = writeStream.ToArray();
writeStream.Close();
}
zipStream.Close();
}
}
}
}
catch (System.Exception ex)
{
throw new Exception("解压字节数组发生错误", ex);
}
}
return result;
}

为了测试该类,我写了一个WinForm程序,界面如下:

可以将文件和文件夹拖放到压缩列表中,选中压缩列表中的对象可以按Delete键进行删除。文件解压区域也可以将要解压的文件拖放到文件路径输入文本框。实际测试可以正确压缩和解压,包括设置密码,压缩和解压操作和WinRAR完全兼容。如果您在代码中发现问题或有可以优化完善的地方,欢迎指出,谢谢!

程序源代码下载:http://files.cnblogs.com/files/conexpress/SharpZipTest.zip

 

C#压缩库SharpZipLib的应用的更多相关文章

  1. ICSharpCode.SharpZipLib 开源压缩库使用示例

    官方网站:http://www.icsharpcode.net/OpenSource/SharpZipLib/Default.aspx 插件描述: ICSharpCode.SharpZipLib.dl ...

  2. [转]Snappy压缩库安装和使用之一

    Snappy压缩库安装和使用之一 原文地址:http://blog.csdn.net/luo6620378xu/article/details/8521223 近日需要在毕业设计中引入一个压缩库,要求 ...

  3. 3D文件压缩库——Draco简析

    3D文件压缩库——Draco简析 今年1月份时,google发布了名为“Draco”的3D图形开源压缩库,下载了其代码来看了下,感觉虽然暂时用不到,但还是有前途的,故简单做下分析. 注:Draco 代 ...

  4. 【神经网络与深度学习】Google Snappy - 一个高速压缩库

    Snappy已经被Google开源,作为一个压缩库,它可以利用单颗Intel Corei7处理器内核处理至少每秒250MB~500MB的数据流. Snappy的前身是Zippy.虽然只是一个数据压缩库 ...

  5. Intel发布神经网络压缩库Distiller:快速利用前沿算法压缩PyTorch模型——AttributeError: module ‘tensorboard' has no attribute 'lazy'

    转载自:CSDN Nine-days   近日,Intel 开源了一个用于神经网络压缩的开源 Python 软件包 Distiller,它可以减少深度神经网络的内存占用.加快推断速度及节省能耗.Dis ...

  6. 【转载】C# 开源库大全非常好

    原文地址:http://m.blog.csdn.net/woddle/article/details/37311877 C#开源大全 商业协作和项目管理平台-TeamLab 网络视频会议软件-VMuk ...

  7. C#开源

    商业协作和项目管理平台-TeamLab 网络视频会议软件-VMukti 驰骋工作流程引擎-ccflow [免费]正则表达式测试工具-Regex-Tester Windows-Phone-7-SDK E ...

  8. C# 开源项目一

    商业协作和项目管理平台-TeamLab 网络视频会议软件-VMukti 驰骋工作流程引擎-ccflow [免费]正则表达式测试工具-Regex-Tester Windows-Phone-7-SDK E ...

  9. C#开源大全--汇总(转)

    商业协作和项目管理平台-TeamLab 网络视频会议软件-VMukti 驰骋工作流程引擎-ccflow [免费]正则表达式测试工具-Regex-Tester Windows-Phone-7-SDK E ...

随机推荐

  1. css 图片内容在不同分辨率下居中显示(演示的图片宽度是1920px,当图片宽度大于显示屏的宽度时)

    1.img 图片内容在不同分辨率下居中显示(如果隐藏多余,在img外面套一个div  设定overflow: hidden.div的大小就是img显示区域的大小) <!DOCTYPE html& ...

  2. 封装ajax(二)闭包的形式

    (function(){ var $=(function(){ function create(){ if(window.XMLHttpRequest){ var xhr=new XMLHttpReq ...

  3. 日志分析_使用shell完整日志分析案例

    一.需求分析 1. 日志文件每天生成一份(需要将日志文件定时上传至hdfs) 2. 分析日志文件中包含的字段:访问IP,访问时间,访问URL,访问状态,访问流量 3. 现在有"昨日" ...

  4. Switch语句的case穿透

    Switch语句的case穿透 一 switch语句几点说明: 1. case后面只能是常量,不能是变量,而且,多个case后面的值不能出现相同的. 2.case后面表达式可以接受: 基本数据类型,b ...

  5. java面试问题整理-垃圾回收

    对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址.大小以及使用情况.通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象,通过这种方式确定哪些对象是"可达的" ...

  6. java常用集合框架底层实现简介与注意点

    Collection: ArrayList:1:底层实现是数组,默认长度是10.2:add(),判断是否数组越界,是数组扩容为原来的两倍.3:remove(),copy数组,size-1,释放空虚的空 ...

  7. uwsgi 安装配置

    安装uwsgi# pip install uwsgi 配置uwsgi:首先要明确的是,如果你喜欢用命令行的方式(如shell)敲命令,那可以省去任何配置.但是,绝大多数人,还是不愿意记那么长的命令,反 ...

  8. SQL常用字段类型

    中文常用字段类型 1.   名称类    nvarchar(10) 2.   数量       int 3.   时间      date 4.   货币      money 5.   编号     ...

  9. Linux Vsftpd 连接超时解决方法(被动模式)

    http://blog.csdn.net/qq_15766181/article/details/46554643 使用 FileZilla FTP Client 连接 Vsftpd FTP,在没有配 ...

  10. select case巧用 oracle

    在做报表的时候,经常会用到分段统计数据,这时候,case就比较有用了: 小例子: SELECT   sh.dc_code, g.bg_code,                   TO_CHAR ( ...