C#实现Zip压缩解压实例

| 发布     | 分类 C#  | 标签 C#  Zip 



参考文档《C#实现Zip压缩解压实例》他这个有几个Bug

[官网下载]SharpZipLib.chm

[官网下载]SharpZipLib

[官网下载] SharpZipLib Dll

[本地下载]SharpZipLib Dll




    private static void SetCode()
    {
        // 需要注意的是 默认编码如果有中文的文件名或目录将会乱码,甚至解压的数据出错。所以设置一下支持中文的编码
        ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage;
    }



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using ICSharpCode.SharpZipLib;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;

/// <summary> 
/// 适用与ZIP压缩 
/// </summary> 
public class ZipHelper
{

    private static void SetCode()
    {
        // 需要注意的是 默认编码如果有中文的文件名或目录将会乱码,甚至解压的数据出错。所以设置一下支持中文的编码
        ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage;
    }


    private static List<string> ignoreExts = new List<string>(new string[]{ ".meta", ".manifest"});
    private static List<string> ignoreFiles = new List<string>(new string[]{ ".ds_store"});

    #region 压缩

    /// <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)
    {
        SetCode();

        bool result = true;
        string[] folders, files;
        ZipEntry ent = null;
        FileStream fs = null;
        FileInfo fileInfo = null;
        Crc32 crc = new Crc32();

        try
        {
            folders = Directory.GetDirectories(folderToZip, "*", SearchOption.AllDirectories);
            files = Directory.GetFiles(folderToZip, "*.*", SearchOption.AllDirectories)
                .Where(s => !ignoreExts.Contains(Path.GetExtension(s).ToLower()) && !ignoreFiles.Contains(Path.GetFileName(s).ToLower()) ).ToArray();


            parentFolderName = folderToZip;
            if (!parentFolderName.EndsWith("/"))
                parentFolderName += "/";

            // 可以不需要压入文件夹。压人后在Mac下用默认的zip工具解压不了
//                foreach(string folder in folders)
//                {
//                    ent = new ZipEntry(folder.Replace(parentFolderName, "") + "/");
//                    zipStream.PutNextEntry(ent);
//                    zipStream.Flush();
//                }

            foreach(string file in files)
            {
                fileInfo = new FileInfo(file);
                fs = File.OpenRead(file);

                byte[] buffer = new byte[fs.Length];
                fs.Read(buffer, 0, buffer.Length);
                ent = new ZipEntry(file.Replace(parentFolderName, ""));
                ent.DateTime = fileInfo.LastWriteTime;
                ent.Size = fs.Length;

                fs.Close();
                
                crc.Reset();
                crc.Update(buffer);

                ent.Crc = crc.Value;
                zipStream.PutNextEntry(ent);
                zipStream.Write(buffer, 0, buffer.Length);
            }
            
             
        }
        catch
        {
            result = false;
        }
        finally
        {
            if (fs != null)
            {
                fs.Close();
                fs.Dispose();
            }
            if (ent != null)
            {
                ent = null;
            }
            GC.Collect();
            GC.Collect(1);
        }
        return result;
    }

    /// <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)
    {
        bool result = false;
        if (!Directory.Exists(folderToZip))
            return result;

        ZipOutputStream zipStream = new ZipOutputStream(File.Create(zipedFile));
        zipStream.SetLevel(9);
        if (!string.IsNullOrEmpty(password)) zipStream.Password = password;


        string fullPath = Path.GetFullPath(folderToZip);
        string parentPath = Path.GetFullPath(fullPath + "/../");

        result = ZipDirectory(fullPath, zipStream, parentPath);

        zipStream.Finish();
        zipStream.Close();

        return result;
    }

    /// <summary> 
    /// 压缩文件夹 
    /// </summary> 
    /// <param name="folderToZip">要压缩的文件夹路径</param> 
    /// <param name="zipedFile">压缩文件完整路径</param> 
    /// <returns>是否压缩成功</returns> 
    public static bool ZipDirectory(string folderToZip, string zipedFile)
    {
        bool result = ZipDirectory(folderToZip, zipedFile, null);
        return result;
    }

    /// <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)
    {
        SetCode();

        bool result = true;
        ZipOutputStream zipStream = null;
        FileStream fs = null;
        ZipEntry ent = null;

        if (!File.Exists(fileToZip))
            return false;

        try
        {
            fs = File.OpenRead(fileToZip);
            byte[] buffer = new byte[fs.Length];
            fs.Read(buffer, 0, buffer.Length);
            fs.Close();

            fs = File.Create(zipedFile);
            zipStream = new ZipOutputStream(fs);
            if (!string.IsNullOrEmpty(password)) zipStream.Password = password;
            ent = new ZipEntry(Path.GetFileName(fileToZip));
            zipStream.PutNextEntry(ent);
            zipStream.SetLevel(6);

            zipStream.Write(buffer, 0, buffer.Length);

        }
        catch
        {
            result = false;
        }
        finally
        {
            if (zipStream != null)
            {
                zipStream.Finish();
                zipStream.Close();
            }
            if (ent != null)
            {
                ent = null;
            }
            if (fs != null)
            {
                fs.Close();
                fs.Dispose();
            }
        }
        GC.Collect();
        GC.Collect(1);

        return result;
    }

    /// <summary> 
    /// 压缩文件 
    /// </summary> 
    /// <param name="fileToZip">要压缩的文件全名</param> 
    /// <param name="zipedFile">压缩后的文件名</param> 
    /// <returns>压缩结果</returns> 
    public static bool ZipFile(string fileToZip, string zipedFile)
    {
        bool result = ZipFile(fileToZip, zipedFile, null);
        return result;
    }

    /// <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)
    {
        bool result = false;
        if (Directory.Exists(fileToZip))
            result = ZipDirectory(fileToZip, zipedFile, password);
        else if (File.Exists(fileToZip))
            result = ZipFile(fileToZip, zipedFile, password);

        return result;
    }

    /// <summary> 
    /// 压缩文件或文件夹 
    /// </summary> 
    /// <param name="fileToZip">要压缩的路径</param> 
    /// <param name="zipedFile">压缩后的文件名</param> 
    /// <returns>压缩结果</returns> 
    public static bool Zip(string fileToZip, string zipedFile)
    {
        bool result = Zip(fileToZip, zipedFile, null);
        return result;

    }

    #endregion

    #region 解压

    /// <summary> 
    /// 解压功能(解压压缩文件到指定目录) 
    /// </summary> 
    /// <param name="fileToUnZip">待解压的文件</param> 
    /// <param name="zipedFolder">指定解压目标目录</param> 
    /// <param name="password">密码</param> 
    /// <returns>解压结果</returns> 
    public static bool UnZip(string zipFilePath, string unZipDir, string password)
    {

        try
        {
            SetCode();

            if (zipFilePath == string.Empty)
            {
                throw new Exception("压缩文件不能为空!");
            }
            if (!File.Exists(zipFilePath))
            {
                throw new FileNotFoundException("压缩文件不存在!");
            }
            //解压文件夹为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹  
            if (unZipDir == string.Empty)
                unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), Path.GetFileNameWithoutExtension(zipFilePath));
            
            if (!unZipDir.EndsWith("/"))
                unZipDir += "/";

            UnZip(File.OpenRead(zipFilePath), unZipDir, password);
        }
        catch(Exception e)
        {
            UnityEngine.Debug.LogError(e);
            return false;
        }

        return true;
    }

    public static bool UnZip(Stream baseInputStream, string unZipDir, string password)
    {
        try
        {
            SetCode();

            if (!unZipDir.EndsWith("/"))
                unZipDir += "/";

            if (!Directory.Exists(unZipDir))
                Directory.CreateDirectory(unZipDir);

            using (var s = new ZipInputStream(baseInputStream))
            {
                if(!string.IsNullOrEmpty(password)) s.Password = password;

                ZipEntry theEntry;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    string directoryName = Path.GetDirectoryName(theEntry.Name);
                    string fileName = Path.GetFileName(theEntry.Name);

                    if (!string.IsNullOrEmpty(directoryName))
                    {
                        Directory.CreateDirectory(unZipDir + directoryName);
                    }
                    if (directoryName != null && !directoryName.EndsWith("/"))
                    {
                    }
                    if (fileName != String.Empty)
                    {
                        using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name))
                        {

                            int size;
                            byte[] data = new byte[2048];
                            while (true)
                            {
                                size = s.Read(data, 0, data.Length);
                                if (size > 0)
                                {
                                    streamWriter.Write(data, 0, size);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        catch(Exception e)
        {
            UnityEngine.Debug.LogError(e);
            return false;
        }

        return true;
    }

    /// <summary> 
    /// 解压功能(解压压缩文件到指定目录) 
    /// </summary> 
    /// <param name="fileToUnZip">待解压的文件</param> 
    /// <param name="zipedFolder">指定解压目标目录</param> 
    /// <returns>解压结果</returns> 
    public static bool UnZip(string fileToUnZip, string zipedFolder)
    {
        bool result = UnZip(fileToUnZip, zipedFolder, null);
        return result;
    }


    public static bool UnZip(Stream baseInputStream, string unZipDir)
    {
        return UnZip(baseInputStream, unZipDir, null);
    }


    public static bool UnZip(byte[] data, string unZipDir)
    {
        MemoryStream stream = new MemoryStream(data);
        stream.Position = 0;
        bool result =  UnZip(stream, unZipDir, null);
        stream.Dispose();
        stream.Close();
        return result;
    }
    #endregion
}



using UnityEngine;
using System.Collections;
using System.IO;

public class TestZip : MonoBehaviour {

    

    [ContextMenu("ZipDir")]
    public void ZipDir()
    {
        string dir = "dir";
        string zipFile = "blog.zip";
        ZipHelper.ZipDirectory(dir, zipFile);
    }

    [ContextMenu("UnZip")]
    public void UnZip()
    {

        string zipFile = "blog.zip";
        string outDir = "zipout";
        ZipHelper.UnZip(zipFile, outDir);
    }


    [ContextMenu("UnZip2")]
    public void UnZip2()
    {
        StartCoroutine(LoadZip());
    }

    IEnumerator LoadZip()
    {
        string zipFile = "blog.zip";
        string outDir = "zipout";
        WWW www = new WWW("file:///" + Application.dataPath + "/../" + zipFile);
        yield return www;


        ZipHelper.UnZip(www.bytes, outDir);
    }
}




上一篇: C# Java AES 协议加密
下一篇: c#使用多线程的几种方式示例详解