程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> 如何壓縮多個文件/文件夾(GZipStream and C#)

如何壓縮多個文件/文件夾(GZipStream and C#)

編輯:關於C#

在.Net Framework 2.0 中添加了System.IO.Compression 類來實現對文件的壓縮/解壓(GZipStream方 法),下面我們來看一個簡單的例子.

Code1:

1    public static void Compress(string filePath, string zipPath)
2    {
3      FileStream sourceFile = File.OpenRead(filePath);
4      FileStream destinationFile = File.Create(zipPath);
5      byte[] buffer = new byte[sourceFile.Length];
6      GZipStream zip = null;
7      try
8      {
9        sourceFile.Read(buffer, 0, buffer.Length);
10        zip = new GZipStream(destinationFile, CompressionMode.Compress);
11        zip.Write(buffer, 0, buffer.Length);
12      }
13      catch
14      {
15        throw;
16      }
17      finally
18      {
19        zip.Close();
20        sourceFile.Close();
21        destinationFile.Close();
22      }
23    }
24
25    public static void Decompress(string zipPath,string filePath)
26    {
27      FileStream sourceFile = File.OpenRead(zipPath);
28
29      string path = filePath.Replace(Path.GetFileName(filePath), "");
30
31      if(!Directory.Exists(path))
32        Directory.CreateDirectory(path);
33
34      FileStream destinationFile = File.Create(filePath);
35      GZipStream unzip = null;
36      byte[] buffer = new byte[sourceFile.Length];
37      try
38      {
39        unzip = new GZipStream(sourceFile, CompressionMode.Decompress, true);
40        int numberOfBytes = unzip.Read(buffer, 0, buffer.Length);
41
42        destinationFile.Write(buffer, 0, numberOfBytes);
43      }
44      catch
45      {
46        throw;
47      }
48      finally
49      {
50        sourceFile.Close();
51        destinationFile.Close();
52        unzip.Close();
53      }
54    }

用例:

1.壓縮

1      string folder = Path.Combine(Server.MapPath("~"), "TestCompress");
2      string file = "file1.txt";
3      string zip = "myzip";
4
5      SampleCompress.Compress(Path.Combine(folder, file), Path.Combine(folder, zip));

2.解壓

1      string folder = Path.Combine(Server.MapPath("~"), "TestCompress");
2      string file = "file1.txt";
3      string zip = "myzip";
4
5      SampleCompress.Decompress(Path.Combine(folder, zip),
Path.Combine (Path.Combine(folder, "zipfolder"), file));

由代碼和使用例子我們可以了解到,Code1 只是支持單個文本文件的壓縮/解壓, 代碼非常簡單,但是卻 實際上卻沒什麼用途,功能太少,只是讓你有個初步的認識.下面介紹Code2來實現本文的主題內容.

Code2:

    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="folders">Array of Folder string</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[] folders, string 

lpBaseFolder, string lpDestFolder, string zipFileName)
        {
            //support compress folder
            IList<FileInfo> list = new List<FileInfo>();
            foreach (FileInfo li in files)
                list.Add(li);
            foreach (string str in folders)
            {
                DirectoryInfo di = new DirectoryInfo(str);
                foreach (FileInfo info in di.GetFiles("*.*", 

SearchOption.AllDirectories))
                {
                    list.Add(info);
                }
            }
            return Compress(list.ToArray(), 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>
        public static GZipResult Compress(FileInfo[] files, string lpBaseFolder, string 

lpDestFolder, string zipFileName)
        {
            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, string zipFileName, 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, bool writeFiles, 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 (!lpSrcFolder.EndsWith("\\"))
            {
                lpSrcFolder += "\\";
            }
            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;
        }
    }
    public class GZipFileInfo
    {
        public int Index = 0;
        public string RelativePath = null;
        public DateTime ModifiedDate;
        public int Length = 0;
        public bool AddedToTempFile = false;
        public bool RestoreRequested = false;
        public bool Restored = false;
        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;
        }
    }
    public class GZipResult
    {
        public GZipFileInfo[] Files = null;
        public int FileCount = 0;
        public long TempFileSize = 0;
        public long ZipFileSize = 0;
        public int CompressionPercent = 0;
        public string TempFile = null;
        public string ZipFile = null;
        public bool TempFileDeleted = false;
        public bool Errors = false;
    }

用例:

1,壓縮

1    string folder = Path.Combine(Server.MapPath("~"), "TestCompress");
2      FileInfo[] info = { new FileInfo(Path.Combine(folder, "file2.ppt")),
new FileInfo(Path.Combine(folder,"file3.doc")) };

3      GZip.Compress(info, new string[] { Path.Combine(folder, "img") }, folder, folder, "myzip2.zip");

2,解壓

1    string folder = Path.Combine(Server.MapPath("~"), "TestCompress");
2    GZip.Decompress(folder, Path.Combine(folder,"newfolder"), "myzip2.zip");

Code2代碼很長,但是卻很好用,在上面用例中我對兩個文件和一個文件夾壓縮,壓縮後保存 到"myzip2.zip"文件中,這只是其中一個重載的版本,原代碼來源於http://www.vwd- cms.com/Forum/Forums.aspx?topic=18 ,可惜作者在網上給出的代碼Bug很多,無法正常運行,不過作者的 辛勞還是值得稱贊的.修改後(Code2)已經可以很好的使用了,並增加了壓縮方法的重載.支持多種多個文件 /文件夾的壓縮和解壓還原(支持中文).下面簡單介紹下工作原理:讀取多文件,格式化後,按照某種規則保 存到一個文件中(上面用例保存到myzip2.gzip文件中)

----------------------------------------------------

0,/file2.ppt,2009-2-5 1:52:07,9216

//.....格式化後內容...//

1,/file3.doc,2009-2-5 1:14:54,24064

//.....格式化後內容...//

2,/img/file4.gif,2009-2-3 0:53:47,729

//.....格式化後內容...//

----------------------------------------------------

在整個過程中是通過創建一個臨時文件來處理,解壓中也根據上面內容格式來進行.當然由於這種獨特 的格式,是不支持rar/zip來解壓的.

最後,提供代碼和例子(VS2008開發,.Net Framework 3.5(C Sharp)編寫),希望你喜歡.謝謝!

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved