加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
ByteBuffer.cs 23.70 KB
一键复制 编辑 原始数据 按行查看 历史
zkpursuit 提交于 2020-11-25 11:10 . 移除不必要的方法
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933
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;
//对象池
private static List<ByteBuffer> pool = new List<ByteBuffer>();
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;
}
/// <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;
}
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化