using ET; using System; using System.Collections.Generic; using System.Text; /// /// 字节缓冲处理类,本类仅支持大字节序 /// 本类非线程安全 /// [Serializable] public class ByteBuffer //: ICloneable { //字节缓存区 private byte[] buf; //读取索引 private int readIndex = 0; //写入索引 private int writeIndex = 0; //读取索引标记 private int markReadIndex = 0; //写入索引标记 private int markWirteIndex = 0; //缓存区字节数组的长度 private int capacity; //对象池 [StaticField] private static List pool = new List(); [StaticField] private static int poolMaxCount = 200; //此对象是否池化 private bool isPool = false; /// /// 构造方法 /// /// 初始容量 private ByteBuffer(int capacity) { this.buf = new byte[capacity]; this.capacity = capacity; this.readIndex = 0; this.writeIndex = 0; } /// /// 构造方法 /// /// 初始字节数组 private ByteBuffer(byte[] bytes) { this.buf = new byte[bytes.Length]; Array.Copy(bytes, 0, buf, 0, buf.Length); this.capacity = buf.Length; this.readIndex = 0; this.writeIndex = bytes.Length + 1; } /// /// 构建一个capacity长度的字节缓存区ByteBuffer对象 /// /// 初始容量 /// /// true表示获取一个池化的ByteBuffer对象,池化的对象必须在调用Dispose后才会推入池中,此方法为线程安全的。 /// 当为true时,从池中获取的对象的实际capacity值。 /// /// ByteBuffer对象 public static ByteBuffer Allocate(int capacity, bool fromPool = false) { if(!fromPool) { return new ByteBuffer(capacity); } lock (pool) { ByteBuffer bbuf; if (pool.Count == 0) { bbuf = new ByteBuffer(capacity) { isPool = true }; return bbuf; } int lastIndex = pool.Count - 1; bbuf = pool[lastIndex]; pool.RemoveAt(lastIndex); if (!bbuf.isPool) { bbuf.isPool = true; } return bbuf; } } /// /// 构建一个以bytes为字节缓存区的ByteBuffer对象,一般不推荐使用 /// /// 初始字节数组 /// /// true表示获取一个池化的ByteBuffer对象,池化的对象必须在调用Dispose后才会推入池中,此方法为线程安全的。 /// /// ByteBuffer对象 public static ByteBuffer Allocate(byte[] bytes, bool fromPool = false) { if (!fromPool) { return new ByteBuffer(bytes); } lock (pool) { ByteBuffer bbuf; if (pool.Count == 0) { bbuf = new ByteBuffer(bytes) { isPool = true }; return bbuf; } int lastIndex = pool.Count - 1; bbuf = pool[lastIndex]; bbuf.WriteBytes(bytes); pool.RemoveAt(lastIndex); if (!bbuf.isPool) { bbuf.isPool = true; } return bbuf; } } /// /// 根据value,确定大于此length的最近的2次方数,如length=7,则返回值为8;length=12,则返回16 /// /// 参考容量 /// 比参考容量大的最接近的2次方数 private int FixLength(int value) { if (value == 0) { return 1; } value--; value |= value >> 1; value |= value >> 2; value |= value >> 4; value |= value >> 8; value |= value >> 16; return value + 1; } /// /// 翻转字节数组,如果本地字节序列为低字节序列,则进行翻转以转换为高字节序列 /// /// 待转为高字节序的字节数组 /// 高字节序列的字节数组 private byte[] Flip(byte[] bytes) { if (!BitConverter.IsLittleEndian) { Array.Reverse(bytes); } return bytes; } /// /// 确定内部字节缓存数组的大小 /// /// 当前容量 /// 将来的容量 /// 当前缓冲区的最大容量 private int FixSizeAndReset(int currLen, int futureLen) { if (futureLen > currLen) { //以原大小的2次方数的两倍确定内部字节缓存区大小 int size = FixLength(currLen) * 2; if (futureLen > size) { //以将来的大小的2次方的两倍确定内部字节缓存区大小 size = FixLength(futureLen) * 2; } byte[] newbuf = new byte[size]; Array.Copy(buf, 0, newbuf, 0, currLen); buf = newbuf; capacity = size; } return futureLen; } /// /// 将bytes字节数组从startIndex开始的length字节写入到此缓存区 /// /// 待写入的字节数据 /// 写入的开始位置 /// 写入的长度 public void WriteBytes(byte[] bytes, int startIndex, int length) { int offset = length - startIndex; if (offset <= 0) return; int total = offset + writeIndex; int len = buf.Length; FixSizeAndReset(len, total); for (int i = writeIndex, j = startIndex; i < total; i++, j++) { buf[i] = bytes[j]; } writeIndex = total; } /// /// 将字节数组中从0到length的元素写入缓存区 /// /// 待写入的字节数据 /// 写入的长度 public void WriteBytes(byte[] bytes, int length) { WriteBytes(bytes, 0, length); } /// /// 将字节数组全部写入缓存区 /// /// 待写入的字节数据 public void WriteBytes(byte[] bytes) { WriteBytes(bytes, bytes.Length); } /// /// 将一个ByteBuffer的有效字节区写入此缓存区中 /// /// 待写入的字节缓存区 public void Write(ByteBuffer buffer) { if (buffer == null) return; if (buffer.ReadableBytes <= 0) return; WriteBytes(buffer.ToArray()); } /// /// 写入一个int16数据 /// /// short数据 public void WriteShort(short value) { WriteBytes(Flip(BitConverter.GetBytes(value))); } /// /// 写入一个uint16数据 /// /// ushort数据 public void WriteUshort(ushort value) { WriteBytes(Flip(BitConverter.GetBytes(value))); } /// /// 写入一个int32数据 /// /// int数据 public void WriteInt(int value) { WriteBytes(Flip(BitConverter.GetBytes(value))); } /// /// 写入一个uint32数据 /// /// uint数据 public void WriteUint(uint value) { WriteBytes(Flip(BitConverter.GetBytes(value))); } /// /// 写入一个int64数据 /// /// long数据 public void WriteLong(long value) { WriteBytes(Flip(BitConverter.GetBytes(value))); } /// /// 写入一个uint64数据 /// /// ulong数据 public void WriteUlong(ulong value) { WriteBytes(Flip(BitConverter.GetBytes(value))); } /// /// 写入一个float数据 /// /// float数据 public void WriteFloat(float value) { WriteBytes(Flip(BitConverter.GetBytes(value))); } /// /// 写入一个byte数据 /// /// byte数据 public void WriteByte(byte value) { int afterLen = writeIndex + 1; int len = buf.Length; FixSizeAndReset(len, afterLen); buf[writeIndex] = value; writeIndex = afterLen; } /// /// 写入一个byte数据 /// /// byte数据 public void WriteByte(int value) { byte b = (byte)value; WriteByte(b); } /// /// 写入一个double类型数据 /// /// double数据 public void WriteDouble(double value) { WriteBytes(Flip(BitConverter.GetBytes(value))); } /// /// 写入一个字符 /// /// public void WriteChar(char value) { WriteBytes(Flip(BitConverter.GetBytes(value))); } /// /// 写入一个布尔型数据 /// /// public void WriteBoolean(bool value) { WriteBytes(Flip(BitConverter.GetBytes(value))); } /// /// 读取一个字节 /// /// 字节数据 public byte ReadByte() { byte b = buf[readIndex]; readIndex++; return b; } /// /// 获取从index索引处开始len长度的字节 /// /// /// /// private byte[] Get(int index, int len) { byte[] bytes = new byte[len]; Array.Copy(buf, index, bytes, 0, len); return Flip(bytes); } /// /// 从读取索引位置开始读取len长度的字节数组 /// /// 待读取的字节长度 /// 字节数组 private byte[] Read(int len) { byte[] bytes = Get(readIndex, len); readIndex += len; return bytes; } /// /// 读取一个uint16数据 /// /// ushort数据 public ushort ReadUshort() { return BitConverter.ToUInt16(Read(2), 0); } /// /// 读取一个int16数据 /// /// short数据 public short ReadShort() { return BitConverter.ToInt16(Read(2), 0); } /// /// 读取一个uint32数据 /// /// uint数据 public uint ReadUint() { return BitConverter.ToUInt32(Read(4), 0); } /// /// 读取一个int32数据 /// /// int数据 public int ReadInt() { return BitConverter.ToInt32(Read(4), 0); } /// /// 读取一个uint64数据 /// /// ulong数据 public ulong ReadUlong() { return BitConverter.ToUInt64(Read(8), 0); } /// /// 读取一个long数据 /// /// long数据 public long ReadLong() { return BitConverter.ToInt64(Read(8), 0); } /// /// 读取一个float数据 /// /// float数据 public float ReadFloat() { return BitConverter.ToSingle(Read(4), 0); } /// /// 读取一个double数据 /// /// double数据 public double ReadDouble() { return BitConverter.ToDouble(Read(8), 0); } /// /// 读取一个字符 /// /// public char ReadChar() { return BitConverter.ToChar(Read(2), 0); } /// /// 读取布尔型数据 /// /// public bool ReadBoolean() { return BitConverter.ToBoolean(Read(1), 0); } /// /// 从读取索引位置开始读取len长度的字节到disbytes目标字节数组中 /// /// 读取的字节将存入此字节数组 /// 目标字节数组的写入索引 /// 读取的长度 public void ReadBytes(byte[] disbytes, int disstart, int len) { int size = disstart + len; for (int i = disstart; i < size; i++) { disbytes[i] = this.ReadByte(); } } public string ReadString(int length) { var str = Encoding.UTF8.GetString(buf, readIndex, length); readIndex += length; return str; } /// /// 获取一个字节 /// /// /// public byte GetByte(int index) { return buf[index]; } /// /// 获取一个字节 /// /// public byte GetByte() { return GetByte(readIndex); } /// /// 获取一个双精度浮点数据,不改变数据内容 /// /// 字节索引 /// public double GetDouble(int index) { return BitConverter.ToDouble(Get(index, 8), 0); } /// /// 获取一个双精度浮点数据,不改变数据内容 /// /// public double GetDouble() { return GetDouble(readIndex); } /// /// 获取一个浮点数据,不改变数据内容 /// /// 字节索引 /// public float GetFloat(int index) { return BitConverter.ToSingle(Get(index, 4), 0); } /// /// 获取一个浮点数据,不改变数据内容 /// /// public float GetFloat() { return GetFloat(readIndex); } /// /// 获取一个长整形数据,不改变数据内容 /// /// 字节索引 /// public long GetLong(int index) { return BitConverter.ToInt64(Get(index, 8), 0); } /// /// 获取一个长整形数据,不改变数据内容 /// /// public long GetLong() { return GetLong(readIndex); } /// /// 获取一个长整形数据,不改变数据内容 /// /// 字节索引 /// public ulong GetUlong(int index) { return BitConverter.ToUInt64(Get(index, 8), 0); } /// /// 获取一个长整形数据,不改变数据内容 /// /// public ulong GetUlong() { return GetUlong(readIndex); } /// /// 获取一个整形数据,不改变数据内容 /// /// 字节索引 /// public int GetInt(int index) { return BitConverter.ToInt32(Get(index, 4), 0); } /// /// 获取一个整形数据,不改变数据内容 /// /// public int GetInt() { return GetInt(readIndex); } /// /// 获取一个整形数据,不改变数据内容 /// /// 字节索引 /// public uint GetUint(int index) { return BitConverter.ToUInt32(Get(index, 4), 0); } /// /// 获取一个整形数据,不改变数据内容 /// /// public uint GetUint() { return GetUint(readIndex); } /// /// 获取一个短整形数据,不改变数据内容 /// /// 字节索引 /// public int GetShort(int index) { return BitConverter.ToInt16(Get(index, 2), 0); } /// /// 获取一个短整形数据,不改变数据内容 /// /// public int GetShort() { return GetShort(readIndex); } /// /// 获取一个短整形数据,不改变数据内容 /// /// 字节索引 /// public int GetUshort(int index) { return BitConverter.ToUInt16(Get(index, 2), 0); } /// /// 获取一个短整形数据,不改变数据内容 /// /// public int GetUshort() { return GetUshort(readIndex); } /// /// 获取一个char数据,不改变数据内容 /// /// 字节索引 /// public char GetChar(int index) { return BitConverter.ToChar(Get(index, 2), 0); } /// /// 获取一个char数据,不改变数据内容 /// /// public char GetChar() { return GetChar(readIndex); } /// /// 获取一个布尔数据,不改变数据内容 /// /// 字节索引 /// public bool GetBoolean(int index) { return BitConverter.ToBoolean(Get(index, 1), 0); } /// /// 获取一个布尔数据,不改变数据内容 /// /// public bool GetBoolean() { return GetBoolean(readIndex); } /// /// 清除已读字节并重建缓存区 /// public void DiscardReadBytes() { if (readIndex <= 0) return; int len = buf.Length - readIndex; byte[] newbuf = new byte[len]; Array.Copy(buf, readIndex, newbuf, 0, len); buf = newbuf; writeIndex -= readIndex; markReadIndex -= readIndex; if (markReadIndex < 0) { //markReadIndex = readIndex; markReadIndex = 0; } markWirteIndex -= readIndex; if (markWirteIndex < 0 || markWirteIndex < readIndex || markWirteIndex < markReadIndex) { markWirteIndex = writeIndex; } readIndex = 0; } /// /// 设置/获取读指针位置 /// public int ReaderIndex { get { return readIndex; } set { if (value < 0) return; readIndex = value; } } /// /// 设置/获取写指针位置 /// public int WriterIndex { get { return writeIndex; } set { if (value < 0) return; writeIndex = value; } } /// /// 标记读取的索引位置 /// public void MarkReaderIndex() { markReadIndex = readIndex; } /// /// 标记写入的索引位置 /// public void MarkWriterIndex() { markWirteIndex = writeIndex; } /// /// 将读取的索引位置重置为标记的读取索引位置 /// public void ResetReaderIndex() { readIndex = markReadIndex; } /// /// 将写入的索引位置重置为标记的写入索引位置 /// public void ResetWriterIndex() { writeIndex = markWirteIndex; } /// /// 可读的有效字节数 /// /// 可读的字节数 public int ReadableBytes { get { return writeIndex - readIndex; } } /// /// 获取缓存区容量大小 /// /// 缓存区容量 public int Capacity { get { return this.capacity; } } /// /// 获取可读的字节数组 /// /// 字节数据 public byte[] ToArray() { byte[] bytes = new byte[writeIndex]; Array.Copy(buf, 0, bytes, 0, bytes.Length); return bytes; } //是的,提高性能,就酱 public byte[] GetBuffer() { return buf; } /// /// 复制一个对象,具有与原对象相同的数据,不改变原对象的数据,不包括已读数据 /// /// public ByteBuffer Copy() { if (buf == null) { return new ByteBuffer(16); } if (readIndex < writeIndex) { byte[] newbytes = new byte[writeIndex - readIndex]; Array.Copy(buf, readIndex, newbytes, 0, newbytes.Length); ByteBuffer buffer = new ByteBuffer(newbytes.Length); buffer.WriteBytes(newbytes); buffer.isPool = this.isPool; return buffer; } return new ByteBuffer(16); } /// /// 深度复制,具有与原对象相同的数据,不改变原对象的数据,包括已读数据 /// /// public ByteBuffer Clone() { if (buf == null) { return new ByteBuffer(16); } ByteBuffer newBuf = new ByteBuffer(buf) { capacity = this.capacity, readIndex = this.readIndex, writeIndex = this.writeIndex, markReadIndex = this.markReadIndex, markWirteIndex = this.markWirteIndex, isPool = this.isPool }; return newBuf; } /// /// 遍历所有的字节数据 /// /// public void ForEach(Action action) { for(int i = 0; i < this.ReadableBytes; i++) { action.Invoke(this.buf[i]); } } /// /// 清空此对象,但保留字节缓存数组(空数组) /// public void Clear() { //buf = new byte[buf.Length]; for(int i = 0; i < buf.Length; i++) { buf[i] = 0; } readIndex = 0; writeIndex = 0; markReadIndex = 0; markWirteIndex = 0; capacity = buf.Length; } /// /// 释放对象,清除字节缓存数组,如果此对象为可池化,那么调用此方法将会把此对象推入到池中等待下次调用 /// public void Dispose() { if (isPool) { lock (pool) { if (pool.Count < poolMaxCount) { this.Clear(); pool.Add(this); } else { readIndex = 0; writeIndex = 0; markReadIndex = 0; markWirteIndex = 0; capacity = 0; buf = null; } } } else { readIndex = 0; writeIndex = 0; markReadIndex = 0; markWirteIndex = 0; capacity = 0; buf = null; } } }