📄 zlib.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 + -