使用ICSharpCode.SharpZipLib解压、压缩ZIP文件
因为网上代码很多,本来是不打算贴代码的,但我在使用网上的代码时各种坑,比如解压时的目录和压缩包的根本不一致,压缩的文件在压缩包里面相对路径也不对,使用还是在这边贴了代码
注意
- 下面的方法我没测试过带密码的情况
- public static bool ZipDirectoryToStream(string folderToZip, Stream Stream, string password = null)这个方法里面的Stream可以在压缩完成文件后,拿到压缩的Stream
- 记得using ICSharpCode.SharpZipLib.Zip
/// <summary>
/// 适用于ZIP压缩
/// </summary>
public class ZipHelper
{
#region 压缩
/// <summary>
/// 压缩文件夹
/// </summary>
/// <param name="folderToZip">要压缩的文件夹路径</param>
/// <param name="Stream">压缩前的Stream,方法执行后变为压缩完成后的文件</param>
/// <param name="password">密码</param>
/// <returns>是否成功</returns>
public static bool ZipDirectoryToStream(string folderToZip, Stream Stream, string password = null)
{
return ZipDirectoryToZipStream(folderToZip, Stream, password) != null;
}
/// <summary>
/// 压缩文件夹
/// </summary>
/// <param name="folderToZip">要压缩的文件夹路径</param>
/// <param name="Stream">压缩前的Stream,方法执行后变为压缩完成后的文件</param>
/// <param name="password">密码</param>
/// <returns>是否压缩成功返回ZipOutputStream,否则返回null</returns>
public static ZipOutputStream ZipDirectoryToZipStream(string folderToZip, Stream Stream, string password = null)
{
if (!Directory.Exists(folderToZip))
{
return null;
}
ZipOutputStream zipStream = new ZipOutputStream(Stream);
zipStream.SetLevel(6);
if (!string.IsNullOrEmpty(password))
{
zipStream.Password = password;
}
if (ZipDirectory(folderToZip, zipStream, ""))
{
zipStream.Finish();
return zipStream;
}
GC.Collect(1);
return null;
}
/// <summary>
/// 递归压缩文件夹的内部方法
/// </summary>
/// <param name="folderToZip">要压缩的文件夹路径</param>
/// <param name="zipStream">压缩输出流</param>
/// <param name="parentFolderName">此文件夹的上级文件夹</param>
/// <returns>是否成功</returns>
private static bool ZipDirectory(string folderToZip, ZipOutputStream zipStream, string parentFolderName)
{
var crc = new ICSharpCode.SharpZipLib.Checksum.Crc32();
//这段是创建空文件夹,注释掉可以去掉空文件夹(因为在写入文件的时候也会创建文件夹)
//if (!string.IsNullOrEmpty(parentFolderName))
//{
// ent = new ZipEntry(parentFolderName + "/");
// zipStream.PutNextEntry(ent);
// zipStream.Flush();
//}
var files = Directory.GetFiles(folderToZip);
foreach (string file in files)
{
byte[] buffer = File.ReadAllBytes(file);
var ent = new ZipEntry(parentFolderName + "/" + Path.GetFileName(file));
//ent.DateTime = File.GetLastWriteTime(file);//设置文件最后修改时间
ent.DateTime = DateTime.Now;
ent.Size = buffer.Length;
crc.Reset();
crc.Update(buffer);
ent.Crc = crc.Value;
zipStream.PutNextEntry(ent);
zipStream.Write(buffer, 0, buffer.Length);
}
var folders = Directory.GetDirectories(folderToZip);
foreach (var folder in folders)
{
var _parentFolderName = parentFolderName + "\\" + folder.Substring(folder.LastIndexOf('\\') + 1);
if (!ZipDirectory(folder, zipStream, _parentFolderName))
{
return false;
}
}
return true;
}
/// <summary>
/// 压缩文件夹
/// </summary>
/// <param name="folderToZip">要压缩的文件夹路径</param>
/// <param name="zipedFile">压缩文件完整路径</param>
/// <param name="password">密码</param>
/// <returns>是否成功</returns>
public static bool ZipDirectory(string folderToZip, string zipedFile, string password = null)
{
var zipStream = ZipDirectoryToZipStream(folderToZip, new FileStream(zipedFile, FileMode.Create, FileAccess.Write), password);
if (zipStream == null)
{
return false;
}
zipStream.Close();
return true;
}
/// <summary>
/// 压缩文件
/// </summary>
/// <param name="fileToZip">要压缩的文件全名</param>
/// <param name="zipedFile">压缩后的文件名</param>
/// <param name="password">密码</param>
/// <returns>是否成功</returns>
public static bool ZipFile(string fileToZip, string zipedFile, string password = null)
{
if (!File.Exists(fileToZip))
{
return false;
}
var fs = File.OpenRead(fileToZip);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
fs = File.Create(zipedFile);
var ent = new ZipEntry(Path.GetFileName(fileToZip));
using (var zipStream = new ZipOutputStream(fs))
{
if (!string.IsNullOrEmpty(password))
{
zipStream.Password = password;
}
zipStream.PutNextEntry(ent);
zipStream.SetLevel(6);
zipStream.Write(buffer, 0, buffer.Length);
}
if (fs != null)
{
fs.Close();
fs.Dispose();
}
GC.Collect(1);
return true;
}
/// <summary>
/// 压缩文件或文件夹
/// </summary>
/// <param name="fileToZip">要压缩的路径</param>
/// <param name="zipedFile">压缩后的文件名</param>
/// <param name="password">密码</param>
/// <returns>是否成功</returns>
public static bool Zip(string fileToZip, string zipedFile, string password = null)
{
if (Directory.Exists(fileToZip))
{
return ZipDirectory(fileToZip, zipedFile, password);
}
else if (File.Exists(fileToZip))
{
return ZipFile(fileToZip, zipedFile, password);
}
return false;
}
#endregion
#region 解压
/// <summary>
/// 解压功能(解压压缩文件到指定目录)
/// </summary>
/// <param name="fileToUnZip">待解压的文件</param>
/// <param name="zipedFolder">指定解压目标目录</param>
/// <param name="password">密码</param>
/// <returns>是否成功</returns>
public static bool UnZip(string fileToUnZip, string zipedFolder, string password = null)
{
if (!System.IO.File.Exists(fileToUnZip))
{
return false;
}
if (!Directory.Exists(zipedFolder))
{
Directory.CreateDirectory(zipedFolder);
}
if (!zipedFolder.EndsWith("\\"))
{
zipedFolder += "\\";
}
ZipEntry ent = null;
using (var zipStream = new ZipInputStream(System.IO.File.OpenRead(fileToUnZip)))
{
if (!string.IsNullOrEmpty(password))
{
zipStream.Password = password;
}
while ((ent = zipStream.GetNextEntry()) != null)
{
if (ent.IsDirectory)
{
continue;
}
if (string.IsNullOrEmpty(ent.Name))
{
continue;
}
string fileName = zipedFolder + ent.Name.Replace('/', '\\');
var index = ent.Name.LastIndexOf('/');
if (index != -1)
{
string path = zipedFolder + ent.Name.Substring(0, index).Replace('/', '\\');
System.IO.Directory.CreateDirectory(path);
}
var bytes = new byte[ent.Size];
zipStream.Read(bytes, 0, bytes.Length);
System.IO.File.WriteAllBytes(fileName, bytes);
}
}
GC.Collect(1);
return true;
}
#endregion
}