程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 免費開源的.NET多類型文件解壓縮組件SharpZipLib(.NET組件介紹之七),

免費開源的.NET多類型文件解壓縮組件SharpZipLib(.NET組件介紹之七),

編輯:關於.NET

免費開源的.NET多類型文件解壓縮組件SharpZipLib(.NET組件介紹之七),


   前面介紹了六種.NET組件,其中有一種組件是寫文件的壓縮和解壓,現在介紹另一種文件的解壓縮組件SharpZipLib。在這個組件介紹系列中,只為簡單的介紹組件的背景和簡單的應用,讀者在閱讀時可以結合官網的相關介紹和在本地實際操作。

   相關的組件功能非常強大,在筆者的介紹中只是提及到簡單的應用,需要了解更多的操作和特性,可以根據官網介紹,或者查看DLL文件的相關類和方法,以此來擴展相關的業務需要。

   SharpZipLib是一個完全在C#中為.NET平台編寫的Zip,GZip,Tar和BZip2庫。

一.SharpZipLib組件概述:

    ziplib(SharpZipLib,以前的NZipLib)是一個完全在C#為.NET平台編寫的Zip,GZip,Tar和BZip2庫。它實現為一個程序集(可安裝在GAC中),因此可以輕松地集成到其他項目(任何.NET語言)中。 #ziplib的創建者這樣說:“我已經將zip庫移植到C#,因為我需要gzip / zip壓縮,我不想使用libzip.dll或類似的東西我想要的所有在純C#“。

    SharpZipLib官網提供的下載操作:.NET 1.1,.NET 2.0(3.5,4.0),.NET CF 1.0,.NET CF 2.0的裝配:下載237 KB,源代碼和示例下載708 KB;源代碼和示例下載708 KB;幫助文件下載1208 KB;

    SharpZipLib是在GPL下發布,遵守開源協議。

二.SharpZipLib核心類和方法介紹:

    以上簡單的介紹了SharpZipLib組件的相關背景,現在具體看一下該組件的相關核心類和方法:

   

   1.ZipOutputStream類PutNextEntry():

public void PutNextEntry(ZipEntry entry)
{
    bool hasCrc;
    if (entry == null)
    {
        throw new ArgumentNullException("entry");
    }
    if (this.entries == null)
    {
        throw new InvalidOperationException("ZipOutputStream was finished");
    }
    if (this.curEntry != null)
    {
        this.CloseEntry();
    }
    if (this.entries.Count == 0x7fffffff)
    {
        throw new ZipException("Too many entries for Zip file");
    }
    CompressionMethod compressionMethod = entry.CompressionMethod;
    int defaultCompressionLevel = this.defaultCompressionLevel;
    entry.Flags &= 0x800;
    this.patchEntryHeader = false;
    if (entry.Size == 0L)
    {
        entry.CompressedSize = entry.Size;
        entry.Crc = 0L;
        compressionMethod = CompressionMethod.Stored;
        hasCrc = true;
    }
    else
    {
        hasCrc = (entry.Size >= 0L) && entry.HasCrc;
        if (compressionMethod == CompressionMethod.Stored)
        {
            if (!hasCrc)
            {
                if (!base.CanPatchEntries)
                {
                    compressionMethod = CompressionMethod.Deflated;
                    defaultCompressionLevel = 0;
                }
            }
            else
            {
                entry.CompressedSize = entry.Size;
                hasCrc = entry.HasCrc;
            }
        }
    }
    if (!hasCrc)
    {
        if (!base.CanPatchEntries)
        {
            entry.Flags |= 8;
        }
        else
        {
            this.patchEntryHeader = true;
        }
    }
    if (base.Password != null)
    {
        entry.IsCrypted = true;
        if (entry.Crc < 0L)
        {
            entry.Flags |= 8;
        }
    }
    entry.Offset = this.offset;
    entry.CompressionMethod = compressionMethod;
    this.curMethod = compressionMethod;
    this.sizePatchPos = -1L;
    if ((this.useZip64_ == UseZip64.On) || ((entry.Size < 0L) && (this.useZip64_ == UseZip64.Dynamic)))
    {
        entry.ForceZip64();
    }
    this.WriteLeInt(0x4034b50);
    this.WriteLeShort(entry.Version);
    this.WriteLeShort(entry.Flags);
    this.WriteLeShort((byte) entry.CompressionMethodForHeader);
    this.WriteLeInt((int) entry.DosTime);
    if (hasCrc)
    {
        this.WriteLeInt((int) entry.Crc);
        if (entry.LocalHeaderRequiresZip64)
        {
            this.WriteLeInt(-1);
            this.WriteLeInt(-1);
        }
        else
        {
            this.WriteLeInt(entry.IsCrypted ? (((int) entry.CompressedSize) + 12) : ((int) entry.CompressedSize));
            this.WriteLeInt((int) entry.Size);
        }
    }
    else
    {
        if (this.patchEntryHeader)
        {
            this.crcPatchPos = base.baseOutputStream_.Position;
        }
        this.WriteLeInt(0);
        if (this.patchEntryHeader)
        {
            this.sizePatchPos = base.baseOutputStream_.Position;
        }
        if (entry.LocalHeaderRequiresZip64 || this.patchEntryHeader)
        {
            this.WriteLeInt(-1);
            this.WriteLeInt(-1);
        }
        else
        {
            this.WriteLeInt(0);
            this.WriteLeInt(0);
        }
    }
    byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
    if (buffer.Length > 0xffff)
    {
        throw new ZipException("Entry name too long.");
    }
    ZipExtraData extraData = new ZipExtraData(entry.ExtraData);
    if (entry.LocalHeaderRequiresZip64)
    {
        extraData.StartNewEntry();
        if (hasCrc)
        {
            extraData.AddLeLong(entry.Size);
            extraData.AddLeLong(entry.CompressedSize);
        }
        else
        {
            extraData.AddLeLong(-1L);
            extraData.AddLeLong(-1L);
        }
        extraData.AddNewEntry(1);
        if (!extraData.Find(1))
        {
            throw new ZipException("Internal error cant find extra data");
        }
        if (this.patchEntryHeader)
        {
            this.sizePatchPos = extraData.CurrentReadIndex;
        }
    }
    else
    {
        extraData.Delete(1);
    }
    if (entry.AESKeySize > 0)
    {
        AddExtraDataAES(entry, extraData);
    }
    byte[] entryData = extraData.GetEntryData();
    this.WriteLeShort(buffer.Length);
    this.WriteLeShort(entryData.Length);
    if (buffer.Length > 0)
    {
        base.baseOutputStream_.Write(buffer, 0, buffer.Length);
    }
    if (entry.LocalHeaderRequiresZip64 && this.patchEntryHeader)
    {
        this.sizePatchPos += base.baseOutputStream_.Position;
    }
    if (entryData.Length > 0)
    {
        base.baseOutputStream_.Write(entryData, 0, entryData.Length);
    }
    this.offset += (30 + buffer.Length) + entryData.Length;
    if (entry.AESKeySize > 0)
    {
        this.offset += entry.AESOverheadSize;
    }
    this.curEntry = entry;
    this.crc.Reset();
    if (compressionMethod == CompressionMethod.Deflated)
    {
        base.deflater_.Reset();
        base.deflater_.SetLevel(defaultCompressionLevel);
    }
    this.size = 0L;
    if (entry.IsCrypted)
    {
        if (entry.AESKeySize > 0)
        {
            this.WriteAESHeader(entry);
        }
        else if (entry.Crc < 0L)
        {
            this.WriteEncryptionHeader(entry.DosTime << 0x10);
        }
        else
        {
            this.WriteEncryptionHeader(entry.Crc);
        }
    }
}

 

   2.ZipOutputStream類Finish():

public override void Finish()
{
    if (this.entries != null)
    {
        if (this.curEntry != null)
        {
            this.CloseEntry();
        }
        long count = this.entries.Count;
        long sizeEntries = 0L;
        foreach (ZipEntry entry in this.entries)
        {
            this.WriteLeInt(0x2014b50);
            this.WriteLeShort(0x33);
            this.WriteLeShort(entry.Version);
            this.WriteLeShort(entry.Flags);
            this.WriteLeShort((short) entry.CompressionMethodForHeader);
            this.WriteLeInt((int) entry.DosTime);
            this.WriteLeInt((int) entry.Crc);
            if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL))
            {
                this.WriteLeInt(-1);
            }
            else
            {
                this.WriteLeInt((int) entry.CompressedSize);
            }
            if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL))
            {
                this.WriteLeInt(-1);
            }
            else
            {
                this.WriteLeInt((int) entry.Size);
            }
            byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
            if (buffer.Length > 0xffff)
            {
                throw new ZipException("Name too long.");
            }
            ZipExtraData extraData = new ZipExtraData(entry.ExtraData);
            if (entry.CentralHeaderRequiresZip64)
            {
                extraData.StartNewEntry();
                if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL))
                {
                    extraData.AddLeLong(entry.Size);
                }
                if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL))
                {
                    extraData.AddLeLong(entry.CompressedSize);
                }
                if (entry.Offset >= 0xffffffffL)
                {
                    extraData.AddLeLong(entry.Offset);
                }
                extraData.AddNewEntry(1);
            }
            else
            {
                extraData.Delete(1);
            }
            if (entry.AESKeySize > 0)
            {
                AddExtraDataAES(entry, extraData);
            }
            byte[] entryData = extraData.GetEntryData();
            byte[] buffer3 = (entry.Comment != null) ? ZipConstants.ConvertToArray(entry.Flags, entry.Comment) : new byte[0];
            if (buffer3.Length > 0xffff)
            {
                throw new ZipException("Comment too long.");
            }
            this.WriteLeShort(buffer.Length);
            this.WriteLeShort(entryData.Length);
            this.WriteLeShort(buffer3.Length);
            this.WriteLeShort(0);
            this.WriteLeShort(0);
            if (entry.ExternalFileAttributes != -1)
            {
                this.WriteLeInt(entry.ExternalFileAttributes);
            }
            else if (entry.IsDirectory)
            {
                this.WriteLeInt(0x10);
            }
            else
            {
                this.WriteLeInt(0);
            }
            if (entry.Offset >= 0xffffffffL)
            {
                this.WriteLeInt(-1);
            }
            else
            {
                this.WriteLeInt((int) entry.Offset);
            }
            if (buffer.Length > 0)
            {
                base.baseOutputStream_.Write(buffer, 0, buffer.Length);
            }
            if (entryData.Length > 0)
            {
                base.baseOutputStream_.Write(entryData, 0, entryData.Length);
            }
            if (buffer3.Length > 0)
            {
                base.baseOutputStream_.Write(buffer3, 0, buffer3.Length);
            }
            sizeEntries += ((0x2e + buffer.Length) + entryData.Length) + buffer3.Length;
        }
        using (ZipHelperStream stream = new ZipHelperStream(base.baseOutputStream_))
        {
            stream.WriteEndOfCentralDirectory(count, sizeEntries, this.offset, this.zipComment);
        }
        this.entries = null;
    }
}

    3.ZipEntry類Clone():

public object Clone()
{
    ZipEntry entry = (ZipEntry) base.MemberwiseClone();
    if (this.extra != null)
    {
        entry.extra = new byte[this.extra.Length];
        Array.Copy(this.extra, 0, entry.extra, 0, this.extra.Length);
    }
    return entry;
}

 

   4.ZipOutputStream類Write():

public override void Write(byte[] buffer, int offset, int count)
{
    if (this.curEntry == null)
    {
        throw new InvalidOperationException("No open entry.");
    }
    if (buffer == null)
    {
        throw new ArgumentNullException("buffer");
    }
    if (offset < 0)
    {
        throw new ArgumentOutOfRangeException("offset", "Cannot be negative");
    }
    if (count < 0)
    {
        throw new ArgumentOutOfRangeException("count", "Cannot be negative");
    }
    if ((buffer.Length - offset) < count)
    {
        throw new ArgumentException("Invalid offset/count combination");
    }
    this.crc.Update(buffer, offset, count);
    this.size += count;
    switch (this.curMethod)
    {
        case CompressionMethod.Stored:
            if (base.Password != null)
            {
                this.CopyAndEncrypt(buffer, offset, count);
            }
            else
            {
                base.baseOutputStream_.Write(buffer, offset, count);
            }
            break;

        case CompressionMethod.Deflated:
            base.Write(buffer, offset, count);
            break;
    }
}

 

三.SharpZipLib實例:

  1.壓縮單個文件:

        /// <summary>
        /// 壓縮單個文件
        /// </summary>
        /// <param name="fileToZip">要壓縮的文件</param>
        /// <param name="zipedFile">壓縮後的文件</param>
        /// <param name="compressionLevel">壓縮等級</param>
        /// <param name="blockSize">每次寫入大小</param>
        public static void ZipFile(string fileToZip, string zipedFile, int compressionLevel, int blockSize)
        {
            if (string.IsNullOrEmpty(fileToZip))
            {
                throw new ArgumentNullException(fileToZip);
            }
            if (string.IsNullOrEmpty(zipedFile))
            {
                throw new ArgumentNullException(zipedFile);
            }
            if (!File.Exists(fileToZip))
            {
                throw new FileNotFoundException("指定要壓縮的文件: " + fileToZip + " 不存在!");
            }
            try
            {
                using (var zipFile = File.Create(zipedFile))
                {
                    using (var zipStream = new ZipOutputStream(zipFile))
                    {
                        using (var streamToZip = new FileStream(fileToZip, FileMode.Open, FileAccess.Read))
                        {
                            var fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\", StringComparison.Ordinal) + 1);
                            var zipEntry = new ZipEntry(fileName);
                            zipStream.PutNextEntry(zipEntry);
                            zipStream.SetLevel(compressionLevel);
                            var buffer = new byte[blockSize];
                            try
                            {
                                int sizeRead;
                                do
                                {
                                    sizeRead = streamToZip.Read(buffer, 0, buffer.Length);
                                    zipStream.Write(buffer, 0, sizeRead);
                                }
                                while (sizeRead > 0);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception(ex.Message);
                            }
                            streamToZip.Close();
                        }
                        zipStream.Finish();
                        zipStream.Close();
                    }
                    zipFile.Close();
                }
            }
            catch (IOException ioex)
            {
                throw new IOException(ioex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

        }

   2. 壓縮單個文件:

       /// <summary>
        /// 壓縮單個文件
        /// </summary>
        /// <param name="fileToZip">要進行壓縮的文件名</param>
        /// <param name="zipedFile">壓縮後生成的壓縮文件名</param>
        public static void ZipFile(string fileToZip, string zipedFile)
        {
            if (string.IsNullOrEmpty(fileToZip))
            {
                throw new ArgumentException(fileToZip);
            }
            if (string.IsNullOrEmpty(zipedFile))
            {
                throw new ArgumentException(zipedFile);
            }
            if (!File.Exists(fileToZip))
            {
                throw new FileNotFoundException("指定要壓縮的文件: " + fileToZip + " 不存在!");
            }
            try
            {
                using (var fs = File.OpenRead(fileToZip))
                {
                    var buffer = new byte[fs.Length];
                    fs.Read(buffer, 0, buffer.Length);
                    fs.Close();
                    using (var zipFile = File.Create(zipedFile))
                    {
                        using (var zipStream = new ZipOutputStream(zipFile))
                        {
                            var fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\", StringComparison.Ordinal) + 1);
                            var zipEntry = new ZipEntry(fileName);
                            zipStream.PutNextEntry(zipEntry);
                            zipStream.SetLevel(5);
                            zipStream.Write(buffer, 0, buffer.Length);
                            zipStream.Finish();
                            zipStream.Close();
                        }
                    }
                }
            }
            catch (IOException ioex)
            {
                throw new IOException(ioex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

        }

   3.壓縮多層目錄:

        /// <summary>
        /// 壓縮多層目錄
        /// </summary>
        /// <param name="strDirectory">目錄</param>
        /// <param name="zipedFile">壓縮文件</param>
        public static void ZipFileDirectory(string strDirectory, string zipedFile)
        {
            if (string.IsNullOrEmpty(strDirectory))
            {
                throw new ArgumentException(strDirectory);
            }
            if (string.IsNullOrEmpty(zipedFile))
            {
                throw new ArgumentException(zipedFile);
            }
            using (var zipFile = File.Create(zipedFile))
            {
                using (var s = new ZipOutputStream(zipFile))
                {
                    ZipSetp(strDirectory, s, "");
                }
            }
        }

    4.遞歸遍歷目錄:

       /// <summary>
        /// 遞歸遍歷目錄
        /// </summary>
        /// <param name="strDirectory">目錄</param>
        /// <param name="s">ZipOutputStream對象</param>
        /// <param name="parentPath">父路徑</param>
        private static void ZipSetp(string strDirectory, ZipOutputStream s, string parentPath)
        {
            if (strDirectory[strDirectory.Length - 1] != Path.DirectorySeparatorChar)
            {
                strDirectory += Path.DirectorySeparatorChar;
            }
            var crc = new Crc32();

            var filenames = Directory.GetFileSystemEntries(strDirectory);
            try
            {
                // 遍歷所有的文件和目錄
                foreach (var file in filenames)
                {
                    // 先當作目錄處理如果存在這個目錄就遞歸Copy該目錄下面的文件
                    if (Directory.Exists(file))
                    {
                        var pPath = parentPath;
                        pPath += file.Substring(file.LastIndexOf("\\", StringComparison.Ordinal) + 1);
                        pPath += "\\";
                        ZipSetp(file, s, pPath);
                    }
                    // 否則直接壓縮文件
                    else
                    {
                        //打開壓縮文件
                        using (var fs = File.OpenRead(file))
                        {
                            var buffer = new byte[fs.Length];
                            fs.Read(buffer, 0, buffer.Length);
                            var fileName = parentPath + file.Substring(file.LastIndexOf("\\", StringComparison.Ordinal) + 1);
                            var entry = new ZipEntry(fileName)
                            {
                                DateTime = DateTime.Now,
                                Size = fs.Length
                            };
                            fs.Close();
                            crc.Reset();
                            crc.Update(buffer);
                            entry.Crc = crc.Value;
                            s.PutNextEntry(entry);
                            s.Write(buffer, 0, buffer.Length);
                        }
                    }
                }
            }
            catch (IOException ioex)
            {
                throw new IOException(ioex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

        }

    5.解壓縮一個 zip 文件:

       /// <summary>
        /// 解壓縮一個 zip 文件。
        /// </summary>
        /// <param name="zipedFile">The ziped file.</param>
        /// <param name="strDirectory">The STR directory.</param>
        /// <param name="password">zip 文件的密碼。</param>
        /// <param name="overWrite">是否覆蓋已存在的文件。</param>
        public void UnZip(string zipedFile, string strDirectory, string password, bool overWrite)
        {
            if (string.IsNullOrEmpty(zipedFile))
            {
                throw new ArgumentException(zipedFile);
            }
            if (string.IsNullOrEmpty(strDirectory))
            {
                throw new ArgumentException(strDirectory);
            }
            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentException(password);
            }
            if (strDirectory == "")
            {
                strDirectory = Directory.GetCurrentDirectory();
            }
            if (!strDirectory.EndsWith("\\"))
            {
                strDirectory = strDirectory + "\\";
            }
            try
            {
                using (var s = new ZipInputStream(File.OpenRead(zipedFile)))
                {
                    s.Password = password;
                    ZipEntry theEntry;
                    while ((theEntry = s.GetNextEntry()) != null)
                    {
                        var directoryName = string.Empty;
                        var pathToZip = theEntry.Name;
                        if (pathToZip != "")
                        {
                            directoryName = Path.GetDirectoryName(pathToZip) + "\\";
                        }
                        var fileName = Path.GetFileName(pathToZip);
                        Directory.CreateDirectory(strDirectory + directoryName);
                        if (fileName == "") continue;
                        if ((!File.Exists(strDirectory + directoryName + fileName) || !overWrite) &&
                            (File.Exists(strDirectory + directoryName + fileName))) continue;
                        using (var streamWriter = File.Create(strDirectory + directoryName + fileName))
                        {
                            var data = new byte[2048];
                            while (true)
                            {
                                var size = s.Read(data, 0, data.Length);

                                if (size > 0)
                                    streamWriter.Write(data, 0, size);
                                else
                                    break;
                            }
                            streamWriter.Close();
                        }
                    }

                    s.Close();
                }
            }
            catch (IOException ioex)
            {
                throw new IOException(ioex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

        }

四.總結:

   以上是對SharpZipLib組件的相關介紹,本文的講解上比較的淺顯,如果需要深入的學習可以進入官網進行詳細的學習。組件的功能是很強大的,如何在項目中使用組件,完成我們在項目中需要實現的功能,這就是對每個開發者提出了要求,需要我們仔細的去考慮。

   任何學習都需要我們自己去探索和思考,對於一個開發者來說,最重要的就是思考,因為在我們的職業生涯中,沒有什麼的重要性能夠超過思考。如果有不足之處還望各位讀者包含,並留言指正。

 

 

.NET組件介紹系列:

    一款開源免費的.NET文檔操作組件DocX(.NET組件介紹之一)http://www.cnblogs.com/pengze0902/p/6122311.html

    高效而穩定的企業級.NET Office 組件Spire(.NET組件介紹之二)http://www.cnblogs.com/pengze0902/p/6125570.html

    最好的.NET開源免費ZIP庫DotNetZip(.NET組件介紹之三)http://www.cnblogs.com/pengze0902/p/6124659.html

    免費開源的DotNet二維碼操作組件ThoughtWorks.QRCode(.NET組件介紹之四)http://www.cnblogs.com/pengze0902/p/6134506.html

    免費開源的DotNet任務調度組件Quartz.NET(.NET組件介紹之五)http://www.cnblogs.com/pengze0902/p/6128558.html

    免費高效實用的Excel操作組件NPOI(.NET組件介紹之六)http://www.cnblogs.com/pengze0902/p/6150070.html

   免費開源的.NET多類型文件解壓縮組件SharpZipLib(.NET組件介紹之七)http://www.cnblogs.com/pengze0902/p/6159497.html

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