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