⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zlib.cs

📁 PDF文件格式解析库源代码
💻 CS
字号:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace QiHe.CodeLib.Compress
{
    public static class Zlib
    {
        public static void Deflate(Stream input, Stream output)
        {
            BinaryWriter writer = new BinaryWriter(output);
            ZlibStream zlibStream = ZlibStream.DeflateStream();
            zlibStream.WriteHeader(writer);
            QiHe.CodeLib.Compress.Deflate.Compress(input, output);
            zlibStream.Checksum = Adler32.Compute(input, 0, (int)input.Position);
            zlibStream.WriteFooter(writer);
            writer.Flush();
        }

        public static void Inflate(Stream input, Stream output)
        {
            BinaryReader reader = new BinaryReader(input);
            ZlibStream zlibStream = new ZlibStream();
            zlibStream.ReadHeader(reader);
            long pos = output.Position;
            if (zlibStream.CompressMethod == (int)CompressionMethod.Deflate)
            {
                QiHe.CodeLib.Compress.Deflate.Decompress(input, output);
            }
            else
            {
                throw new Exception("Unknown Compression Method: " + zlibStream.CompressMethod);
            }
            int len = (int)(output.Position - pos);
            zlibStream.Checksum = Adler32.Compute(output, pos, len);
            zlibStream.ReadFooter(reader);
        }

        public static byte[] Decode(Stream input)
        {
            MemoryStream output = new MemoryStream();
            Deflate(input, output);
            return output.ToArray();
        }

        public static void Deflate(Stream input, Stream output, CompressionOption level)
        {
            Compress(input, output, CompressionMethod.Deflate, level);
        }

        public static void Compress(Stream input, Stream output, CompressionMethod method, CompressionOption level)
        {
            BinaryWriter writer = new BinaryWriter(output);
            ZlibStream zlibStream = ZlibStream.DeflateStream();
            zlibStream.CompressMethod = (int)method;
            zlibStream.WriteHeader(writer);
            long pos = input.Position;
            Native.Compress(input, output, method, level);
            zlibStream.Checksum = Adler32.Compute(input, pos, (int)(input.Position - pos));
            zlibStream.WriteFooter(writer);
            writer.Flush();
        }

        public static void Decompress(Stream input, Stream output)
        {
            BinaryReader reader = new BinaryReader(input);
            ZlibStream zlibStream = new ZlibStream();
            zlibStream.ReadHeader(reader);
            long pos = output.Position;
            CompressionMethod method = (CompressionMethod)zlibStream.CompressMethod;
            Native.Decompress(input, output, method);
            int len = (int)(output.Position - pos);
            zlibStream.Checksum = Adler32.Compute(output, pos, len);
            zlibStream.ReadFooter(reader);
        }
    }

    public class ZlibStream
    {
        byte CMF;
        byte FLG;
        uint DICTID;
        byte[] compressedData;
        uint ADLER32;

        public ZlibStream() { }

        public static ZlibStream DeflateStream()
        {
            ZlibStream zlibStream = new ZlibStream();
            zlibStream.CompressMethod = (int)CompressionMethod.Deflate;
            zlibStream.CompressionInfo = 7; //32KB
            zlibStream.CompressionLevel = 1;
            return zlibStream;
        }

        public void ReadHeader(BinaryReader reader)
        {
            CMF = reader.ReadByte();
            FLG = reader.ReadByte();
            if (!CheckFlag())
            {
                throw new Exception("zlib header flag illegal");
            }
            if (HasPresetDictionary)
            {
                DICTID = ReadUInt32BigEndian(reader);
            }
        }

        public void ReadFooter(BinaryReader reader)
        {
            uint checksum = ReadUInt32BigEndian(reader);
            if (checksum != ADLER32) //CheckIntegrity
            {
                throw new Exception("Adler chksum doesn't match: " + ADLER32 + " vs. " + checksum);
            }
        }

        private bool CheckFlag()
        {
            return (CMF * 256 + FLG) % 31 == 0;
        }

        private void ValidateFlag()
        {
            FlagCheck = 0;
            FlagCheck = 31 - (CMF * 256 + FLG) % 31;
        }

        private static UInt32 ReadUInt32BigEndian(BinaryReader reader)
        {
            UInt32 value = 0;
            for (int i = 0; i < 4; i++)
            {
                value = (value << 8) | reader.ReadByte();
            }
            return value;
        }

        private static void WriteReadUInt32BigEndian(BinaryWriter writer, uint value)
        {
            for (int i = 3; i >= 0; i--)
            {
                byte bt = (byte)((value >> i * 8) & 0xFF);
                writer.Write(bt);
            }
        }

        public void WriteHeader(BinaryWriter writer)
        {
            ValidateFlag();
            writer.Write(CMF);
            writer.Write(FLG);
            if (HasPresetDictionary)
            {
                writer.Write(DICTID);
            }
        }

        public void WriteFooter(BinaryWriter writer)
        {
            WriteReadUInt32BigEndian(writer, ADLER32);
        }

        /// <summary>
        /// This identifies the compression method used in the file. CM = 8
        /// denotes the "deflate" compression method with a window size up
        /// to 32K.  CM = 15 is reserved.  It might be used in a future
        /// version of this specification to indicate the presence of an
        /// extra field before the compressed data.
        /// </summary>
        public int CompressMethod
        {
            get
            {
                return CMF & 0x0F;
            }
            set
            {
                if (value < 0 || value > 15)
                {
                    throw new ArgumentOutOfRangeException("CompressMethod");
                }
                CMF = (byte)((CMF & 0xF0) | value);
            }
        }

        /// <summary>
        /// For CM = 8, CINFO is the base-2 logarithm of the LZ77 window
        /// size, minus eight (CINFO=7 indicates a 32K window size). Values
        /// of CINFO above 7 are not allowed in this version of the
        /// specification.  CINFO is not defined in this specification for
        /// CM not equal to 8.
        /// </summary>
        public int CompressionInfo
        {
            get
            {
                return (CMF & 0xF0) >> 4;
            }
            set
            {
                if (value < 0 || value > 15)
                {
                    throw new ArgumentOutOfRangeException("CompressionInfo");
                }
                CMF = (byte)((CMF & 0x0F) | (value << 4));
            }
        }

        public int FlagCheck
        {
            get { return FLG & 0x1F; }
            set { FLG = (byte)((FLG & 0xE0) | value); }
        }

        /// <summary>
        /// Preset dictionary is used or not
        /// </summary>
        public bool HasPresetDictionary
        {
            get { return (FLG & 0x20) != 0; }
            set { FLG = (byte)(FLG | 0x20); }
        }

        /// <summary>
        /// These flags are available for use by specific compression
        /// methods.  The "deflate" method (CM = 8) sets these flags as
        /// follows:
        /// 
        ///   0 - compressor used fastest algorithm
        ///   1 - compressor used fast algorithm
        ///   2 - compressor used default algorithm
        ///   3 - compressor used maximum compression, slowest algorithm
        /// 
        /// The information in FLEVEL is not needed for decompression; it
        /// is there to indicate if recompression might be worthwhile.
        /// </summary>
        public int CompressionLevel
        {
            get { return (FLG & 0xC0) >> 6; }
            set { FLG = (byte)((FLG & 0x3F) | (value << 6)); }
        }

        /// <summary>
        /// The dictionary is a sequence of
        /// bytes which are initially fed to the compressor without
        /// producing any compressed output. DICTID is the Adler-32 checksum
        /// of this sequence of bytes. 
        /// The decompressor can use this identifier to determine
        /// which dictionary has been used by the compressor.
        /// </summary>
        public uint DictionaryID
        {
            get { return DICTID; }
            set { DICTID = value; }
        }

        /// <summary>
        /// For compression method 8, the compressed data is stored in the
        /// deflate compressed data format.
        /// </summary>
        public byte[] CompressedData
        {
            get { return compressedData; }
            set { compressedData = value; }
        }

        /// <summary>
        /// This is a checksum value of the uncompressed data
        /// (excluding any dictionary data) computed according to Adler-32
        /// algorithm.
        /// </summary>
        public uint Checksum
        {
            get { return ADLER32; }
            set { ADLER32 = value; }
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -