C# ZIP压缩解压
using System;
using System.Collections.Generic; using System.Linq;
using System.Text;
using System.IO;
using System.IO.Compression;
using System.IO.Packaging;
using System.Collections.Specialized;
namespace TestSeriali.App_Code
{
static public class ZipManager
{
///
/// 构造函数
/// 静态类的构造占位符
///
static ZipManager()
{
}
///
/// 将指定路径下的文件打包到指定目录;
///
///
用此方法打包的文件,可以使用 Centran.ZipToolCore.ZipManager.UnCompressPackageTo(string, string) 方法解压还原
///
指定源文件所在路径
///
打包路径及文件名,例如:"d:\\dirName\\fileName.Centran"
public static void CompressFolderTo(string sourcePath, string toPath)
{
CompressFolderTo(sourcePath, toPath, true);
}
///
/// 将指定的.Centan文件包解压到指定目录下,并覆盖已经存在的文件;
///
///
/// 此方法解压的文件是 Centran.ZipToolCore.ZipManager.CompressFolderTo
或 Centran.ZipToolCore.ZipManager.CompressFolderToWithTransaction 生成的
/// 压缩后的文件是
标准
excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载
的ZIP文件可以用第三方工具察看,但是使用第三方工具修改将导致不可预见的问题
///
指定的压缩包文件的全路径,例
如:"d:\\dirName\\fileName.zip"
///
解压路径,尾部路径分隔符为可选,例如:"d:\\bak\\"和"d:\\bak"是等价的
/// 特别地,此参数为true时若,若目标文件没有足够权限覆盖,则导致函数立即异常中止,此时无法确定解压了哪些文件以及还有哪些文件没有解压
///
返回集合,元素是每个解压成功的文件的全路径,不包括没有解压文件的全路径
///
packagePath 是空引用
///
对 packagePath 指定的文件没有足够权限,或被锁定
///
packagePath 指定的包格式不正确,通常是包内文件没有统一的基础路径
///
调用方没有所要求的权限。isOverride为true时,目标文件没有足够权限覆盖
public static HashSet
UnCompressPackageTo(string packagePath,
string toPath)
{
return UnCompressPackageTo(packagePath, toPath, true);
}
///
/// 将指定路径下的文件打包到指定目录;
/// 这个函数支持事务,如果出 ///
/// 这个函数通常会进行大量的IO操作,执行很长时间.该函数将比不带事务特性的 CompressFolderTo 函数占用额外一倍的磁盘盘空间和IO时间
/// 用此方法打包的文件,可以使用 Centran.ZipToolCore.ZipManager.UnCompressPackageTo(string, string) 方法解压还原
/// 压缩后的文件是标准的ZIP文件可以用第三方工具察看,但是使用第三方工具修改将导致不可预见的问题
/// 指定源文件所在路径
/// 打包路径及文件名,例如:"d:\\dirName\\fileName.Centran",如果文件已经存在),则会被追加合并而非删除
/// 但是内部的文件如果冲突(文件的全路径相同则被替换,如包内已经有d"\\bak\\readme.txt",而sourcePath路径下存在一个全路径与之相等的文件则会被替换
/// 是否包含子文件夹及文件
/// 调用方没有所要求的权限。
/// TO DO请将以下异常改为XML注释格式,如上行的格式
/// System.ArgumentException:
/// path 是一个零长度字符串,仅包含空白或者包含一个或多个由 System.IO.Path.InvalidPathChars 定义的无效字符。-
/// 或 - searchPattern 不包含有效模式。
///
/// System.ArgumentNullException:
/// path 或 searchPattern 为 null。
///
/// System.IO.PathTooLongException:
/// 指定的路径、文件名或者两者都超出了系统定义的最大长度。例如,在基于 Windows 的平台上,路径必须小于 248 个字符,文件名必须小于 260
/// 个字符。
///
/// System.IO.DirectoryNotFoundException:
/// 指定的路径无效(例如,它位于未映射的驱动器上)。
/// // 异常:
// System.ArgumentNullException:
// toPath 为 null。
// System.IO.IOException:
// 打开文件时发生 I/O 错误。
//
// System.UnauthorizedAccessException:
// 在当前平台上不支持此操作。- 或 -path 指定了一个目录。- 或 -调用方没有所要求的权限。
//
// System.IO.FileNotFoundException:
// 未找到 path 中指定的文件。
//
// System.Security.SecurityException:
// 调用方没有所要求的权限。
public static void CompressFolderToWithTransaction(string sourcePath,
string toPath, bool includeSubDir)
{
string tmpFile //临时文件的全路径
= Path.GetDirectoryName(toPath); //获取包文件目录路 tmpFile = Path.Combine(tmpFile, Path.GetTempFileName());
File.Copy(toPath, tmpFile, true);
try
{
CompressFolderTo(sourcePath, toPath, includeSubDir);
}
catch //若干出现错误则恢复原有包文件
{
File.Delete(toPath);
File.Move(tmpFile, toPath); //同硬盘下该函数性能很高
throw;
}
finally
{
File.Delete(tmpFile);
}
}
///
/// 将指定路径下的文件打包到指定目录;
/// 这个函数不支持事务,如果出现错误则不能确定包内哪些部件被更改了.
/// 如果要支持事务特性请使用CompressFolderToWithTransaction(string
sourcePath, string toPath, bool includeSubDir)
///
/// 这个函数通常会进行大量的IO操作,执行很长时间.
/// 用此方法打包的文件,可以使用 Centran.ZipToolCore.ZipManager.UnCompressPackageTo(string, string) 方法解压还原
/// 压缩后的文件是标准的ZIP文件可以用第三方工具察看,但是使用第三方工具修改将导致不可预见的问题
/// 下面代码演示将全路径转换为包内部件,和反过来转换的代码
/// Uri uri = PackUriHelper.CreatePartUri(new Uri("d:\\b.txt",
UriKind.Relative));
/// Path.GetFullPath(uri.OriginalString.Substring(1)); //因为 PackagePart URI 为绝对路径,它始终以“/”开头
///
/// 指定源文件所在路径
/// 打包路径及文件名,例如:"d:\\dirName\\fileName.Centran",如果文件已经存在),则会被追加合并而非删除
/// 但是内部的文件如果冲突(文件的全路径相同则被替换,如包内已经有d"\\bak\\readme.txt",而sourcePath路径下存在一个全路径与之相等的文件则会被替换
/// 是否包含子文件夹及文件
/// 调用方没有所要求的权限。
/// TO DO请将以下异常改为XML注释格式,如上行的格式
/// System.ArgumentException:
/// path 是一个零长度字符串,仅包含空白或者包含一个或多个由 System.IO.Path.InvalidPathChars 定义的无效字符。-
/// 或 - searchPattern 不包含有效模式。
///
/// System.ArgumentNullException:
/// path 或 searchPattern 为 null。
///
/// System.IO.PathTooLongException:
/// 指定的路径、文件名或者两者都超出了系统定义的最大长度。例如,在基于 Windows 的平台上,路径必须小于 248 个字符,文件 /// 个字符。
///
/// System.IO.DirectoryNotFoundException:
/// 指定的路径无效(例如,它位于未映射的驱动器上)。
/// // 异常:
// System.ArgumentNullException:
// toPath 为 null。
// System.IO.IOException:
// 打开文件时发生 I/O 错误。
//
// System.UnauthorizedAccessException:
// 在当前平台上不支持此操作。- 或 -path 指定了一个目录。- 或 -调用方
没有所要求的权限。
//
// System.IO.FileNotFoundException:
// 未找到 path 中指定的文件。
//
// System.Security.SecurityException:
// 调用方没有所要求的权限。
public static void CompressFolderTo(string sourcePath, string toPath, bool
includeSubDir)
{
Package pkg = Package.Open(toPath); //此 Open 方法可打开具有默认属性
OpenOrCreate、ReadWrite 和 None 的包
try
{
//获取所有文件名
string[] fileNames = Directory.GetFiles(sourcePath, "*.*", includeSubDir ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
//获取格式化的 PackagePart URI 集合
var uris = from tmp in fileNames
select new { FullPath = tmp, Uri = PackUriHelper.CreatePartUri(new Uri(tmp, UriKind.Relative)) };
//获取所有需要写入部件的集合
var packagePart = from tmp in uris
select new
{
FullPath = tmp.FullPath,
Part = pkg.PartExists(tmp.Uri) ? pkg.GetPart(tmp.Uri) : //要注意存在的部件
pkg.CreatePart(tmp.Uri, System.Net.Mime.MediaTypeNames.Application.Zip, CompressionOption.Normal)
};
//将每个文件写入包
foreach (var item in packagePart)
{
using (Stream stream = item.Part.GetStream(FileMode.Create))
//此方法清空所有打开的流内容。
{
using (FileStream fs = new FileStream(item.FullPath,
FileMode.Open, FileAccess.Read, FileShare.Read)) //此方法与 FileMode 值为 Open、FileAccess 值为 Read 和 FileShare 值为 Read
CopyStream(fs, stream);
}
}
}
finally
{
pkg.Close();
}
}
///
/// 将指定的.Centan文件包解压到指定目录下;
///
///
/// 此方法解压的文件是 Centran.ZipToolCore.ZipManager.C /// 压缩后的文件是标准的ZIP文件可以用第三方工具察看,但是使用第三方工具修改将导致不可预见的问题
/// 指定的压缩包文件的全路径,例如:"d:\\dirName\\fileName.zip"
/// 解压路径,尾部路径分隔符为可选,例如:"d:\\bak\\"和"d:\\bak"是等价的
/// 如果目标文件存在是否覆盖,true覆盖,false不解压重名文件
/// 特别地,此参数为true时若,若目标文件没有足够权限覆盖,则导致函数立即异常中止,此时无法确定解压了哪些文件以及还有哪些文件没有解压
/// 返回集合,元素是每个解压成功的文件的全路径,不包括没有解压文件的全路径
/// packagePath 是空引用
/// 对 packagePath 指定的文件没有足够权限,或被锁定
/// packagePath 指定的包格式不正确,通常是包内文件没有统一的基础路径
/// 调用方没有所要求的权限。isOverride为true时,目标文件没有足够权限覆盖
public static HashSet UnCompressPackageTo(string packagePath,
string toPath, bool isOverride)
{
HashSet hsResult;
Package pkg = Package.Open(packagePath, FileMode.Open, FileAccess.Read,
FileShare.Read);
try
{
//获取所有部件的Uri和源文件绝对路径
var coll = from tmp in pkg.GetParts()
select new { PackPart = tmp, FullPath = Path.GetFullPath(tmp.Uri.OriginalString.Substring(1)) };
if (coll.Count() == 0) //若没有要解压的文件
return new HashSet();
//取得文件全路径中最短目录路径
string strBaseDir = Path.GetDirectoryName(coll.ToList().OrderBy(
c => { return
Path.GetDirectoryName(c.FullPath).Length; }).First().FullPath); //基础目录
if (!coll.All(c => { return c.FullPath.IndexOf(strBaseDir) == 0; }))
//若不是所有文件都有同一个基础目录则
throw new InvalidOperationException("指定的包格式不正确");
//获取解压后目标文件的全路径和源部件的集合
var collDesc = from tmp in coll
select new
{
FullPath = Path.Combine(toPath, tmp.FullPath.Substring(strBaseDir.Length + 1)), //Path.Combine("d:\\","\\s.1
PackPart = tmp.PackPart
};
hsResult = new HashSet();
foreach (var item in collDesc)
{
if (!isOverride && File.Exists(item.FullPath)) //若不要覆盖且
已经存在文件
continue;
Directory.CreateDirectory(Path.GetDirectoryName(item.FullPath)); //创建文件的
目录
using (Stream source = item.PackPart.GetStream(FileMode.Open,
FileAccess.Read),
desc = new FileStream(item.FullPath, FileMode.Create, FileAccess.Write))
CopyStream(source, desc); //复制内容
hsResult.Add(item.FullPath);
}
}
finally
{
pkg.Close();
}
return hsResult;
}
///
/// 将源的流中的数据复制到目标流。
///
/// 要从复制的源流。
/// 要复制到的目标流
private static void CopyStream(Stream source, Stream target)
{
const int bufSize = 0x100000;
byte[] buf = new byte[bufSize];
int bytesRead = 0;
while ((bytesRead = source.Read(buf, 0, bufSize)) > 0)
target.Write(buf, 0, bytesRead);
}
}
}