使用SharpZipLib實現文件壓縮、解壓

接口

public interface IUnZip
{
    /// <summary>   
    /// 功能:解壓zip格式的文件。   
    /// </summary>   
    /// <param name="zipFilePath">壓縮文件路徑</param>   
    /// <param name="unZipDir">解壓文件存放路徑,爲空時默認與壓縮文件同一級目錄下,跟壓縮文件同名的文件夾</param>   
    /// <param name="password">壓縮包密碼</param>
    /// <returns>解壓後文件所在的文件夾</returns>
    string UnZipFile(string zipFilePath, string unZipDir = null, string password = null);
}

public interface IZip
{
    /// <summary>
    /// 將選定的文件壓入一個目標zip中
    /// </summary>
    /// <param name="list">選定的文件/文件夾(路徑的集合)</param>
    /// <param name="targetFileName">壓縮後獲得的zip保存路徑</param> 
    /// <param name="password">壓縮包密碼</param>
    /// <param name="overwrite">若是Zip文件已存在,是否覆蓋</param> 
    /// <param name="level">壓縮等級0—9</param>
    /// <returns>壓縮包路徑</returns>
    void Compress(List<string> list, string targetFileName, string password = null, bool overwrite = true, int level = 9);

    /// <summary>
    /// 將選定的文件壓入一個目標zip中
    /// </summary>
    /// <param name="fileOrDir">選定的文件/文件夾</param>
    /// <param name="targetFileName">壓縮後獲得的zip保存路徑</param>
    /// <param name="password">壓縮包密碼</param>
    /// <param name="overwrite">若是Zip文件已存在,是否覆蓋</param>  
    /// <param name="level">壓縮等級0—9</param>
    /// <returns>壓縮包路徑</returns>
    void Compress(string fileOrDir, string targetFileName, string password = null, bool overwrite = true, int level = 9);
}

public interface IZipHelper:IZip,IUnZip
{
}

實現

public class ZipHelper : IZipHelper
{
    #region 壓縮文件

    /// <inheritdoc/>
    public void Compress(string fileOrDir, string targetFileName, string password = null, bool overwrite = true, int level = 9)
    {
        List<string> list = new List<string> { fileOrDir };
        Compress(list, targetFileName, password, overwrite,level);
    }

    /// <inheritdoc/>
    public void Compress(List<string> list, string targetFileName, string password = null, bool overwrite = true,int level = 9)
    {
        CheckForCompress(list, targetFileName, overwrite);

        //若是已經存在目標文件,刪除
        if (File.Exists(targetFileName))
        {
            File.Delete(targetFileName);
        }

        ZipOutputStream zips = null;
        FileStream fileStream = null;
        try
        {
            fileStream = File.Create(targetFileName);
            zips = new ZipOutputStream(fileStream);
            zips.SetLevel(level % 10);      //壓縮等級
            zips.Password = password;
            foreach (string dir in list)
            {
                if (File.Exists(dir))
                {
                    AddFile("",dir, zips);
                }
                else
                {
                    CompressFolder("", dir, zips);
                }
            }
            zips.Finish();
        }
        catch { throw; }
        finally
        {
            if(fileStream!= null)
            {
                fileStream.Close();
                fileStream.Dispose();
            }
            if(zips!= null)
            {
                zips.Close();
                zips.Dispose();
            }
        }
    }

    #region private
    private void CheckForCompress(List<string> files, string targetFileName, bool overwrite)
    {
        //由於files可能來自不一樣的文件夾,因此不方便自動提供一個默認文件夾,須要提供
        if (!overwrite && File.Exists(targetFileName))
        {
            throw new Exception("目標zip文件已存在!");
        }

        //待壓入的文件或文件夾須要真實存在
        foreach (var item in files)
        {
            if (!File.Exists(item) && !Directory.Exists(item))
            {
                throw new Exception($"文件/文件夾【{item}】不存在!");
            }
        }

        //不能有同名的文件/文件夾
        Dictionary<string, string> dic = new Dictionary<string, string>();
        foreach (var item in files)
        {
            string item_ = item.TrimEnd('/', '\\');
            string fileName = Path.GetFileName(item_);
            if (dic.ContainsKey(fileName))
            {
                throw new Exception($"選中的文件/文件夾中存在同名衝突:【{dic[fileName]}】,【{item_}】");
            }
            else
            {
                dic[fileName] = item_;
            }
        }
    }
    
    private void AddFile(string orignalDir, string file, ZipOutputStream zips)
    {  
        //文件
        FileStream StreamToZip = null;
        try
        {
            //加入ZIP文件條目(爲壓縮文件流提供一個容器)
            StreamToZip = new FileStream(file, FileMode.Open, FileAccess.Read);
            string fileName = Path.GetFileName(file);
            if (!string.IsNullOrEmpty(orignalDir))
            {
                fileName = orignalDir + Path.DirectorySeparatorChar + fileName;
            }
            ZipEntry z = new ZipEntry(fileName);
            zips.PutNextEntry(z);

            //寫入文件流
            int pack = 10240; //10Kb
            byte[] buffer = new byte[pack];

            int size = StreamToZip.Read(buffer, 0, buffer.Length);
            while (size > 0)
            {
                zips.Write(buffer, 0, size);
                size = StreamToZip.Read(buffer, 0, buffer.Length);
            }
        }
        catch { throw; }
        finally
        {
            if (StreamToZip != null)
            {
                StreamToZip.Close();
                StreamToZip.Dispose();
            }
        }
    }
    private void AddFolder(string orignalDir, string folder, ZipOutputStream zips)
    {
        //文件夾
        folder = folder.TrimEnd('/','\\');
        string fileName = Path.GetFileName(folder);
        if (!string.IsNullOrEmpty(orignalDir))
        {
            fileName = orignalDir + Path.DirectorySeparatorChar + fileName ;
        }
        fileName += Path.DirectorySeparatorChar;
        ZipEntry z = new ZipEntry(fileName);
        zips.PutNextEntry(z);
    }
    /// <summary>
    /// 遞歸壓縮文件夾內全部文件和子文件夾
    /// </summary>
    /// <param name="orignalDir">外層文件夾</param>
    /// <param name="dir">被壓縮文件夾</param>
    /// <param name="zips">流</param>
    private void CompressFolder(string orignalDir,string dir, ZipOutputStream zips)
    {
        // 壓縮當前文件夾下全部文件
        string[] names = Directory.GetFiles(dir);
        foreach (string fileName in names)
        {
            AddFile(orignalDir,fileName, zips);
        }
        // 壓縮子文件夾
        names = Directory.GetDirectories(dir);
        foreach (string folderName in names)
        {
            AddFolder(orignalDir, folderName, zips);

            string _orignalDir = Path.GetFileName(folderName);
            if (!string.IsNullOrEmpty(orignalDir))
            {
                _orignalDir = orignalDir + Path.DirectorySeparatorChar + _orignalDir;
            }
            CompressFolder(_orignalDir, folderName, zips);
        }
    }
    #endregion private

    #endregion 壓縮文件

    #region 解壓文件

    /// <inheritdoc/>
    public string UnZipFile(string zipFilePath, string unZipDir = null,string password = null)
    {
        if (!File.Exists(zipFilePath))
        {
            throw new Exception($"壓縮文件【{zipFilePath}】不存在!");
        }
        //解壓文件夾爲空時默認與壓縮文件同一級目錄下,跟壓縮文件同名的文件夾   
        if (string.IsNullOrWhiteSpace(unZipDir))
        {
            unZipDir = Path.GetDirectoryName(zipFilePath);
            string name = Path.GetFileNameWithoutExtension(zipFilePath);
            unZipDir = Path.Combine(unZipDir, name);
        }

        string unZipDir2 = unZipDir;
        char lastChar = unZipDir[unZipDir.Length - 1];
        if (lastChar != '/' && lastChar != '\\')
        {
            unZipDir += Path.DirectorySeparatorChar;
        }

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

        //解壓
        UnZipProcess(zipFilePath, unZipDir, password);

        return unZipDir2;
    }
    private void UnZipProcess(string zipFilePath, string unZipDir, string password)
    {
        ZipInputStream zipInput = null;
        FileStream fileStream = null;
        try
        {
            fileStream = File.OpenRead(zipFilePath);
            zipInput = new ZipInputStream(fileStream);
            zipInput.Password = password;
            ZipEntry theEntry;
            while ((theEntry = zipInput.GetNextEntry()) != null)
            {
                string tempPath = unZipDir + theEntry.Name;
                if (theEntry.IsDirectory)
                {
                    if (!Directory.Exists(tempPath))
                    {
                        Directory.CreateDirectory(tempPath);
                    }
                }
                else
                {
                    using (FileStream streamWriter = File.Create(tempPath))
                    {
                        byte[] buffer = new byte[10240];
                        int size = zipInput.Read(buffer, 0, buffer.Length);
                        while (size > 0)
                        {
                            streamWriter.Write(buffer, 0, size);
                            size = zipInput.Read(buffer, 0, buffer.Length);
                        }
                    }
                }
            }
        }
        catch
        {
            throw;
        }
        finally
        {
            if (fileStream != null)
            {
                fileStream.Close();
                fileStream.Dispose();
            }
            if (zipInput != null)
            {
                zipInput.Close();
                zipInput.Dispose();
            }
        }
    }
      
    #endregion
}
相關文章
相關標籤/搜索