C# GZipStream 压缩 解压

1 篇文章 0 订阅
1 篇文章 0 订阅
(转自:http://www.cnblogs.com/leiOOlei/archive/2011/06/15/2081514.html)      
关于GZipStream压缩解压,网上找了很多资料,完整的不多,要么是针对字符串压缩解压缩的,要么只实现了针对单个文件的压缩解压缩,还有的不支持子文件夹的压缩,实用性都不是很大。(我自己也写过一个类,功能都已经实现,但是感觉还是这个比较全面些。这篇虽然注释不多,但仔细看还是能看明白的。)

      以下整理了压缩解压缩的代码,供以后拿出来翻阅,在项目中可以直接使用这3个类,已通过测试。

      1.首先是有一个描述要压缩的文件类GZipFileInfo,包含了一些文件信息

    /// <summary>
    /// 要压缩的文件信息
    /// </summary>
    public class GZipFileInfo
    {
        /// <summary>
        /// 文件索引
        /// </summary>
        public int Index = 0;
        /// <summary>
        /// 文件相对路径,'/'
        /// </summary>
        public string RelativePath = null;
        public DateTime ModifiedDate;
        /// <summary>
        /// 文件内容长度
        /// </summary>
        public int Length = 0;
        public bool AddedToTempFile = false;
        public bool RestoreRequested = false;
        public bool Restored = false;
        /// <summary>
        /// 文件绝对路径,'\'
        /// </summary>
        public string LocalPath = null;
        public string Folder = null;

        public bool ParseFileInfo(string fileInfo)
        {
            bool success = false;
            try
            {
                if (!string.IsNullOrEmpty(fileInfo))
                {
                    // get the file information
                    string[] info = fileInfo.Split(',');
                    if (info != null && info.Length == 4)
                    {
                        this.Index = Convert.ToInt32(info[0]);
                        this.RelativePath = info[1].Replace("/", "\\");
                        this.ModifiedDate = Convert.ToDateTime(info[2]);
                        this.Length = Convert.ToInt32(info[3]);
                        success = true;
                    }
                }
            }
            catch
            {
                success = false;
            }
            return success;
        }
    }

      2.压缩后生成的压缩包信息GZipResult,描述了压缩包的一些属性,包括大小,文件数,以及其中的每一个文件
/// <summary>
    /// 文件压缩后的压缩包类
    /// </summary>
    public class GZipResult
    {
        /// <summary>
        /// 压缩包中包含的所有文件,包括子目录下的文件
        /// </summary>
        public GZipFileInfo[] Files = null;
        /// <summary>
        /// 要压缩的文件数
        /// </summary>
        public int FileCount = 0;
        public long TempFileSize = 0;
        public long ZipFileSize = 0;
        /// <summary>
        /// 压缩百分比
        /// </summary>
        public int CompressionPercent = 0;
        /// <summary>
        /// 临时文件
        /// </summary>
        public string TempFile = null;
        /// <summary>
        /// 压缩文件
        /// </summary>
        public string ZipFile = null;
        /// <summary>
        /// 是否删除临时文件
        /// </summary>
        public bool TempFileDeleted = false;
        public bool Errors = false;
    }

      3.压缩操作类GZip,包括压缩解压等操作

/// <summary>
/// 压缩文件类
/// </summary>
public class GZip
{
    /// <summary>
    /// Compress
    /// </summary>
    /// <param name="lpSourceFolder">The location of the files to include in the zip file, all files including files in subfolders will be included.</param>
    /// <param name="lpDestFolder">Folder to write the zip file into</param>
    /// <param name="zipFileName">Name of the zip file to write</param>
    public static GZipResult Compress(string lpSourceFolder, string lpDestFolder, string zipFileName)
    {
        return Compress(lpSourceFolder, "*.*", SearchOption.AllDirectories, lpDestFolder, zipFileName, true);
    }

    /// <summary>
    /// Compress
    /// </summary>
    /// <param name="lpSourceFolder">The location of the files to include in the zip file</param>
    /// <param name="searchPattern">Search pattern (ie "*.*" or "*.txt" or "*.gif") to idendify what files in lpSourceFolder to include in the zip file</param>
    /// <param name="searchOption">Only files in lpSourceFolder or include files in subfolders also</param>
    /// <param name="lpDestFolder">Folder to write the zip file into</param>
    /// <param name="zipFileName">Name of the zip file to write</param>
    /// <param name="deleteTempFile">Boolean, true deleted the intermediate temp file, false leaves the temp file in lpDestFolder (for debugging)</param>
    public static GZipResult Compress(string lpSourceFolder, string searchPattern, SearchOption searchOption,string lpDestFolder, string zipFileName, bool deleteTempFile)
    {
        DirectoryInfo di = new DirectoryInfo(lpSourceFolder);
        FileInfo[] files = di.GetFiles("*.*", searchOption);
        return Compress(files, lpSourceFolder, lpDestFolder, zipFileName, deleteTempFile);
    }

    /// <summary>
    /// Compress
    /// </summary>
    /// <param name="files">Array of FileInfo objects to be included in the zip file</param>
    /// <param name="lpBaseFolder">Base folder to use when creating relative paths for the files
    /// stored in the zip file. For example, if lpBaseFolder is 'C:\zipTest\Files\', and there is a file
    /// 'C:\zipTest\Files\folder1\sample.txt' in the 'files' array, the relative path for sample.txt
    /// will be 'folder1/sample.txt'</param>
    /// <param name="lpDestFolder">Folder to write the zip file into</param>
    /// <param name="zipFileName">Name of the zip file to write</param>
    public static GZipResult Compress(FileInfo[] files, string lpBaseFolder, string lpDestFolder, stringzipFileName)
    {
        return Compress(files, lpBaseFolder, lpDestFolder, zipFileName, true);
    }

    /// <summary>
    /// Compress
    /// </summary>
    /// <param name="files">Array of FileInfo objects to be included in the zip file</param>
    /// <param name="lpBaseFolder">Base folder to use when creating relative paths for the files
    /// stored in the zip file. For example, if lpBaseFolder is 'C:\zipTest\Files\', and there is a file
    /// 'C:\zipTest\Files\folder1\sample.txt' in the 'files' array, the relative path for sample.txt
    /// will be 'folder1/sample.txt'</param>
    /// <param name="lpDestFolder">Folder to write the zip file into</param>
    /// <param name="zipFileName">Name of the zip file to write</param>
    /// <param name="deleteTempFile">Boolean, true deleted the intermediate temp file, false leaves the temp file in lpDestFolder (for debugging)</param>
    public static GZipResult Compress(FileInfo[] files, string lpBaseFolder, string lpDestFolder, stringzipFileName, bool deleteTempFile)
    {
        GZipResult result = new GZipResult();

        try
        {
            if (!lpDestFolder.EndsWith("\\"))
            {
                lpDestFolder += "\\";
            }

            string lpTempFile = lpDestFolder + zipFileName + ".tmp";
            string lpZipFile = lpDestFolder + zipFileName;

            result.TempFile = lpTempFile;
            result.ZipFile = lpZipFile;

            if (files != null && files.Length > 0)
            {
                CreateTempFile(files, lpBaseFolder, lpTempFile, result);

                if (result.FileCount > 0)
                {
                    CreateZipFile(lpTempFile, lpZipFile, result);
                }

                // delete the temp file
                if (deleteTempFile)
                {
                    File.Delete(lpTempFile);
                    result.TempFileDeleted = true;
                }
            }
        }
        catch //(Exception ex4)
        {
            result.Errors = true;
        }
        return result;
    }

    private static void CreateZipFile(string lpSourceFile, string lpZipFile, GZipResult result)
    {
        byte[] buffer;
        int count = 0;
        FileStream fsOut = null;
        FileStream fsIn = null;
        GZipStream gzip = null;

        // compress the file into the zip file
        try
        {
            fsOut = new FileStream(lpZipFile, FileMode.Create, FileAccess.Write, FileShare.None);
            gzip = new GZipStream(fsOut, CompressionMode.Compress, true);

            fsIn = new FileStream(lpSourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);
            buffer = new byte[fsIn.Length];
            count = fsIn.Read(buffer, 0, buffer.Length);
            fsIn.Close();
            fsIn = null;

            // compress to the zip file
            gzip.Write(buffer, 0, buffer.Length);

            result.ZipFileSize = fsOut.Length;
            result.CompressionPercent = GetCompressionPercent(result.TempFileSize, result.ZipFileSize);
        }
        catch //(Exception ex1)
        {
            result.Errors = true;
        }
        finally
        {
            if (gzip != null)
            {
                gzip.Close();
                gzip = null;
            }
            if (fsOut != null)
            {
                fsOut.Close();
                fsOut = null;
            }
            if (fsIn != null)
            {
                fsIn.Close();
                fsIn = null;
            }
        }
    }

    private static void CreateTempFile(FileInfo[] files, string lpBaseFolder, string lpTempFile, GZipResult result)
    {
        byte[] buffer;
        int count = 0;
        byte[] header;
        string fileHeader = null;
        string fileModDate = null;
        string lpFolder = null;
        int fileIndex = 0;
        string lpSourceFile = null;
        string vpSourceFile = null;
        GZipFileInfo gzf = null;
        FileStream fsOut = null;
        FileStream fsIn = null;

        if (files != null && files.Length > 0)
        {
            try
            {
                result.Files = new GZipFileInfo[files.Length];

                // open the temp file for writing
                fsOut = new FileStream(lpTempFile, FileMode.Create, FileAccess.Write, FileShare.None);

                foreach (FileInfo fi in files)
                {
                    lpFolder = fi.DirectoryName + "\\";
                    try
                    {
                        gzf = new GZipFileInfo();
                        gzf.Index = fileIndex;

                        // read the source file, get its virtual path within the source folder
                        lpSourceFile = fi.FullName;
                        gzf.LocalPath = lpSourceFile;
                        vpSourceFile = lpSourceFile.Replace(lpBaseFolder, string.Empty);
                        vpSourceFile = vpSourceFile.Replace("\\", "/");
                        gzf.RelativePath = vpSourceFile;

                        fsIn = new FileStream(lpSourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);
                        buffer = new byte[fsIn.Length];
                        count = fsIn.Read(buffer, 0, buffer.Length);
                        fsIn.Close();
                        fsIn = null;

                        fileModDate = fi.LastWriteTimeUtc.ToString();
                        gzf.ModifiedDate = fi.LastWriteTimeUtc;
                        gzf.Length = buffer.Length;

                        fileHeader = fileIndex.ToString() + "," + vpSourceFile + "," + fileModDate + "," + buffer.Length.ToString() + "\n";
                        header = Encoding.Default.GetBytes(fileHeader);

                        fsOut.Write(header, 0, header.Length);
                        fsOut.Write(buffer, 0, buffer.Length);
                        fsOut.WriteByte(10); // linefeed

                        gzf.AddedToTempFile = true;

                        // update the result object
                        result.Files[fileIndex] = gzf;

                        // increment the fileIndex
                        fileIndex++;
                    }
                    catch //(Exception ex1)
                    {
                        result.Errors = true;
                    }
                    finally
                    {
                        if (fsIn != null)
                        {
                            fsIn.Close();
                            fsIn = null;
                        }
                    }
                    if (fsOut != null)
                    {
                        result.TempFileSize = fsOut.Length;
                    }
                }
            }
            catch //(Exception ex2)
            {
                result.Errors = true;
            }
            finally
            {
                if (fsOut != null)
                {
                    fsOut.Close();
                    fsOut = null;
                }
            }
        }

        result.FileCount = fileIndex;
    }

    public static GZipResult Decompress(string lpSourceFolder, string lpDestFolder, string zipFileName)
    {
        return Decompress(lpSourceFolder, lpDestFolder, zipFileName, true, true, null, null, 4096);
    }

    public static GZipResult Decompress(string lpSourceFolder, string lpDestFolder, string zipFileName, boolwriteFiles, string addExtension)
    {
        return Decompress(lpSourceFolder, lpDestFolder, zipFileName, true, writeFiles, addExtension, null, 4096);
    }

    public static GZipResult Decompress(string lpSrcFolder, string lpDestFolder, string zipFileName,
        bool deleteTempFile, bool writeFiles, string addExtension, Hashtable htFiles, int bufferSize)
    {
        GZipResult result = new GZipResult();

        if (!lpDestFolder.EndsWith("\\"))
        {
            lpDestFolder += "\\";
        }

        string lpTempFile = lpSrcFolder + zipFileName + ".tmp";
        string lpZipFile = lpSrcFolder + zipFileName;

        result.TempFile = lpTempFile;
        result.ZipFile = lpZipFile;

        string line = null;
        string lpFilePath = null;
        string lpFolder = null;
        GZipFileInfo gzf = null;
        FileStream fsTemp = null;
        ArrayList gzfs = new ArrayList();
        bool write = false;

        if (string.IsNullOrEmpty(addExtension))
        {
            addExtension = string.Empty;
        }
        else if (!addExtension.StartsWith("."))
        {
            addExtension = "." + addExtension;
        }

        // extract the files from the temp file
        try
        {
            fsTemp = UnzipToTempFile(lpZipFile, lpTempFile, result);
            if (fsTemp != null)
            {
                while (fsTemp.Position != fsTemp.Length)
                {
                    line = null;
                    while (string.IsNullOrEmpty(line) && fsTemp.Position != fsTemp.Length)
                    {
                        line = ReadLine(fsTemp);
                    }

                    if (!string.IsNullOrEmpty(line))
                    {
                        gzf = new GZipFileInfo();
                        if (gzf.ParseFileInfo(line) && gzf.Length > 0)
                        {
                            gzfs.Add(gzf);
                            lpFilePath = lpDestFolder + gzf.RelativePath;
                            lpFolder = GetFolder(lpFilePath);
                            gzf.LocalPath = lpFilePath;

                            write = false;
                            if (htFiles == null || htFiles.ContainsKey(gzf.RelativePath))
                            {
                                gzf.RestoreRequested = true;
                                write = writeFiles;
                            }

                            if (write)
                            {
                                // make sure the folder exists
                                if (!Directory.Exists(lpFolder))
                                {
                                    Directory.CreateDirectory(lpFolder);
                                }

                                // read from fsTemp and write out the file
                                gzf.Restored = WriteFile(fsTemp, gzf.Length, lpFilePath + addExtension, bufferSize);
                            }
                            else
                            {
                                // need to advance fsTemp
                                fsTemp.Position += gzf.Length;
                            }
                        }
                    }
                }
            }
        }
        catch //(Exception ex3)
        {
            result.Errors = true;
        }
        finally
        {
            if (fsTemp != null)
            {
                fsTemp.Close();
                fsTemp = null;
            }
        }

        // delete the temp file
        try
        {
            if (deleteTempFile)
            {
                File.Delete(lpTempFile);
                result.TempFileDeleted = true;
            }
        }
        catch //(Exception ex4)
        {
            result.Errors = true;
        }

        result.FileCount = gzfs.Count;
        result.Files = new GZipFileInfo[gzfs.Count];
        gzfs.CopyTo(result.Files);
        return result;
    }

    private static string ReadLine(FileStream fs)
    {
        string line = string.Empty;

        const int bufferSize = 4096;
        byte[] buffer = new byte[bufferSize];
        byte b = 0;
        byte lf = 10;
        int i = 0;

        while (b != lf)
        {
            b = (byte)fs.ReadByte();
            buffer[i] = b;
            i++;
        }

        line = System.Text.Encoding.Default.GetString(buffer, 0, i - 1);

        return line;
    }

    private static bool WriteFile(FileStream fs, int fileLength, string lpFile, int bufferSize)
    {
        bool success = false;
        FileStream fsFile = null;

        if (bufferSize == 0 || fileLength < bufferSize)
        {
            bufferSize = fileLength;
        }

        int count = 0;
        int remaining = fileLength;
        int readSize = 0;

        try
        {
            byte[] buffer = new byte[bufferSize];
            fsFile = new FileStream(lpFile, FileMode.Create, FileAccess.Write, FileShare.None);

            while (remaining > 0)
            {
                if (remaining > bufferSize)
                {
                    readSize = bufferSize;
                }
                else
                {
                    readSize = remaining;
                }

                count = fs.Read(buffer, 0, readSize);
                remaining -= count;

                if (count == 0)
                {
                    break;
                }

                fsFile.Write(buffer, 0, count);
                fsFile.Flush();

            }
            fsFile.Flush();
            fsFile.Close();
            fsFile = null;

            success = true;
        }
        catch //(Exception ex2)
        {
            success = false;
        }
        finally
        {
            if (fsFile != null)
            {
                fsFile.Flush();
                fsFile.Close();
                fsFile = null;
            }
        }
        return success;
    }

    private static string GetFolder(string lpFilePath)
    {
        string lpFolder = lpFilePath;
        int index = lpFolder.LastIndexOf("\\");
        if (index != -1)
        {
            lpFolder = lpFolder.Substring(0, index + 1);
        }
        return lpFolder;
    }
    private static FileStream UnzipToTempFile(string lpZipFile, string lpTempFile, GZipResult result)
    {
        FileStream fsIn = null;
        GZipStream gzip = null;
        FileStream fsOut = null;
        FileStream fsTemp = null;

        const int bufferSize = 4096;
        byte[] buffer = new byte[bufferSize];
        int count = 0;

        try
        {
            fsIn = new FileStream(lpZipFile, FileMode.Open, FileAccess.Read, FileShare.Read);
            result.ZipFileSize = fsIn.Length;

            fsOut = new FileStream(lpTempFile, FileMode.Create, FileAccess.Write, FileShare.None);
            gzip = new GZipStream(fsIn, CompressionMode.Decompress, true);
            while (true)
            {
                count = gzip.Read(buffer, 0, bufferSize);
                if (count != 0)
                {
                    fsOut.Write(buffer, 0, count);
                }
                if (count != bufferSize)
                {
                    break;
                }
            }
        }
        catch //(Exception ex1)
        {
            result.Errors = true;
        }
        finally
        {
            if (gzip != null)
            {
                gzip.Close();
                gzip = null;
            }
            if (fsOut != null)
            {
                fsOut.Close();
                fsOut = null;
            }
            if (fsIn != null)
            {
                fsIn.Close();
                fsIn = null;
            }
        }

        fsTemp = new FileStream(lpTempFile, FileMode.Open, FileAccess.Read, FileShare.None);
        if (fsTemp != null)
        {
            result.TempFileSize = fsTemp.Length;
        }
        return fsTemp;
    }

    private static int GetCompressionPercent(long tempLen, long zipLen)
    {
        double tmp = (double)tempLen;
        double zip = (double)zipLen;
        double hundred = 100;

        double ratio = (tmp - zip) / tmp;
        double pcnt = ratio * hundred;

        return (int)pcnt;
    }
}

压缩解压缩的操作如下:
    //Compress三个参数分别是“要压缩的目标目录”,“保存压缩文件的目录”,压缩文件名
    GZip.Compress(@"E:\much\", @"E:\much\", "ziptest");
    
    //Decompress三个参数分别是"压缩包所在目录","要解压到的目录",“压缩包名”
    //如果压缩包所在目录不存在则解压不会成功
    GZip.Decompress(@"E:\much\zip\", @"E:\much\zip\", "ziptest");
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值