在写网络程序的时候,经常需要往一个数组里面压数据或者取数据,而Java中再Java.nio中有个ByteBuffer能很方便的实现,Delphi中也有个Stream类有着同样的功能,这里我就模仿JAVA用C#做个最基础的ByteBuffer类
下面是代码
using System;
namespace System.ByteBuffer
{
/// <summary>
/// 创建一个可变长的Byte数组方便Push数据和Pop数据
/// 数组的最大长度为1024,超过会产生溢出
/// 数组的最大长度由常量MAX_LENGTH设定
///
/// 注:由于实际需要,可能要从左到右取数据,所以这里
/// 定义的Pop函数并不是先进后出的函数,而是从0开始.
///
/// @Author: Red_angelX
/// </summary>
class ByteBuffer
{
//数组的最大长度
private const int MAX_LENGTH = 1024;
//固定长度的中间数组
private byte[] TEMP_BYTE_ARRAY = new byte[MAX_LENGTH];
//当前数组长度
private int CURRENT_LENGTH = 0;
//当前Pop指针位置
private int CURRENT_POSITION = 0;
//最后返回数组
private byte[] RETURN_ARRAY;
/// <summary>
/// 默认构造函数
/// </summary>
public ByteBuffer()
{
this.Initialize();
}
/// <summary>
/// 重载的构造函数,用一个Byte数组来构造
/// </summary>
/// <param name="bytes">用于构造ByteBuffer的数组</param>
public ByteBuffer(byte[] bytes)
{
this.Initialize();
this.PushByteArray(bytes);
}
/// <summary>
/// 获取当前ByteBuffer的长度
/// </summary>
public int Length
{
get
{
return CURRENT_LENGTH;
}
}
/// <summary>
/// 获取/设置当前出栈指针位置
/// </summary>
public int Position
{
get
{
return CURRENT_POSITION;
}
set
{
CURRENT_POSITION = value;
}
}
/// <summary>
/// 获取ByteBuffer所生成的数组
/// 长度必须小于 [MAXSIZE]
/// </summary>
/// <returns>Byte[]</returns>
public byte[] ToByteArray()
{
//分配大小
RETURN_ARRAY = new byte[CURRENT_LENGTH];
//调整指针
Array.Copy(TEMP_BYTE_ARRAY, 0, RETURN_ARRAY, 0, CURRENT_LENGTH);
return RETURN_ARRAY;
}
/// <summary>
/// 初始化ByteBuffer的每一个元素,并把当前指针指向头一位
/// </summary>
public void Initialize()
{
TEMP_BYTE_ARRAY.Initialize();
CURRENT_LENGTH = 0;
CURRENT_POSITION = 0;
}
/// <summary>
/// 向ByteBuffer压入一个字节
/// </summary>
/// <param name="by">一位字节</param>
public void PushByte(byte by)
{
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = by;
}
/// <summary>
/// 向ByteBuffer压入数组
/// </summary>
/// <param name="ByteArray">数组</param>
public void PushByteArray(byte[] ByteArray)
{
//把自己CopyTo目标数组
ByteArray.CopyTo(TEMP_BYTE_ARRAY, CURRENT_LENGTH);
//调整长度
CURRENT_LENGTH += ByteArray.Length;
}
/// <summary>
/// 向ByteBuffer压入两字节的Short
/// </summary>
/// <param name="Num">2字节Short</param>
public void PushUInt16(UInt16 Num)
{
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0xff00) >> 8) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)((Num & 0x00ff) & 0xff);
}
/// <summary>
/// 向ByteBuffer压入一个无符Int值
/// </summary>
/// <param name="Num">4字节UInt32</param>
public void PushInt(UInt32 Num)
{
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0xff000000) >> 24) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0x00ff0000) >> 16) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0x0000ff00) >> 8) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)((Num & 0x000000ff) & 0xff);
}
/// <summary>
/// 向ByteBuffer压入一个Long值
/// </summary>
/// <param name="Num">4字节Long</param>
public void PushLong(long Num)
{
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0xff000000) >> 24) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0x00ff0000) >> 16) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0x0000ff00) >> 8) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)((Num & 0x000000ff) & 0xff);
}
/// <summary>
/// 从ByteBuffer的当前位置弹出一个Byte,并提升一位
/// </summary>
/// <returns>1字节Byte</returns>
public byte PopByte()
{
byte ret = TEMP_BYTE_ARRAY[CURRENT_POSITION++];
return ret;
}
/// <summary>
/// 从ByteBuffer的当前位置弹出一个Short,并提升两位
/// </summary>
/// <returns>2字节Short</returns>
public UInt16 PopUInt16()
{
//溢出
if (CURRENT_POSITION + 1 >= CURRENT_LENGTH)
{
return 0;
}
UInt16 ret = (UInt16)(TEMP_BYTE_ARRAY[CURRENT_POSITION] << 8 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 1]);
CURRENT_POSITION += 2;
return ret;
}
/// <summary>
/// 从ByteBuffer的当前位置弹出一个uint,并提升4位
/// </summary>
/// <returns>4字节UInt</returns>
public uint PopUInt()
{
if (CURRENT_POSITION + 3 >= CURRENT_LENGTH)
return 0;
uint ret = (uint)(TEMP_BYTE_ARRAY[CURRENT_POSITION] << 24 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 1] << 16 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 2] << 8 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 3]);
CURRENT_POSITION += 4;
return ret;
}
/// <summary>
/// 从ByteBuffer的当前位置弹出一个long,并提升4位
/// </summary>
/// <returns>4字节Long</returns>
public long PopLong()
{
if (CURRENT_POSITION + 3 >= CURRENT_LENGTH)
return 0;
long ret = (long)(TEMP_BYTE_ARRAY[CURRENT_POSITION] << 24 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 1] << 16 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 2] << 8 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 3]);
CURRENT_POSITION += 4;
return ret;
}
/// <summary>
/// 从ByteBuffer的当前位置弹出长度为Length的Byte数组,提升Length位
/// </summary>
/// <param name="Length">数组长度</param>
/// <returns>Length长度的byte数组</returns>
public byte[] PopByteArray(int Length)
{
//溢出
if (CURRENT_POSITION + Length >= CURRENT_LENGTH)
{
return new byte[0];
}
byte[] ret = new byte[Length];
Array.Copy(TEMP_BYTE_ARRAY, CURRENT_POSITION, ret, 0, Length);
//提升位置
CURRENT_POSITION += Length;
return ret;
}
}
}
namespace System.ByteBuffer
{
/// <summary>
/// 创建一个可变长的Byte数组方便Push数据和Pop数据
/// 数组的最大长度为1024,超过会产生溢出
/// 数组的最大长度由常量MAX_LENGTH设定
///
/// 注:由于实际需要,可能要从左到右取数据,所以这里
/// 定义的Pop函数并不是先进后出的函数,而是从0开始.
///
/// @Author: Red_angelX
/// </summary>
class ByteBuffer
{
//数组的最大长度
private const int MAX_LENGTH = 1024;
//固定长度的中间数组
private byte[] TEMP_BYTE_ARRAY = new byte[MAX_LENGTH];
//当前数组长度
private int CURRENT_LENGTH = 0;
//当前Pop指针位置
private int CURRENT_POSITION = 0;
//最后返回数组
private byte[] RETURN_ARRAY;
/// <summary>
/// 默认构造函数
/// </summary>
public ByteBuffer()
{
this.Initialize();
}
/// <summary>
/// 重载的构造函数,用一个Byte数组来构造
/// </summary>
/// <param name="bytes">用于构造ByteBuffer的数组</param>
public ByteBuffer(byte[] bytes)
{
this.Initialize();
this.PushByteArray(bytes);
}
/// <summary>
/// 获取当前ByteBuffer的长度
/// </summary>
public int Length
{
get
{
return CURRENT_LENGTH;
}
}
/// <summary>
/// 获取/设置当前出栈指针位置
/// </summary>
public int Position
{
get
{
return CURRENT_POSITION;
}
set
{
CURRENT_POSITION = value;
}
}
/// <summary>
/// 获取ByteBuffer所生成的数组
/// 长度必须小于 [MAXSIZE]
/// </summary>
/// <returns>Byte[]</returns>
public byte[] ToByteArray()
{
//分配大小
RETURN_ARRAY = new byte[CURRENT_LENGTH];
//调整指针
Array.Copy(TEMP_BYTE_ARRAY, 0, RETURN_ARRAY, 0, CURRENT_LENGTH);
return RETURN_ARRAY;
}
/// <summary>
/// 初始化ByteBuffer的每一个元素,并把当前指针指向头一位
/// </summary>
public void Initialize()
{
TEMP_BYTE_ARRAY.Initialize();
CURRENT_LENGTH = 0;
CURRENT_POSITION = 0;
}
/// <summary>
/// 向ByteBuffer压入一个字节
/// </summary>
/// <param name="by">一位字节</param>
public void PushByte(byte by)
{
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = by;
}
/// <summary>
/// 向ByteBuffer压入数组
/// </summary>
/// <param name="ByteArray">数组</param>
public void PushByteArray(byte[] ByteArray)
{
//把自己CopyTo目标数组
ByteArray.CopyTo(TEMP_BYTE_ARRAY, CURRENT_LENGTH);
//调整长度
CURRENT_LENGTH += ByteArray.Length;
}
/// <summary>
/// 向ByteBuffer压入两字节的Short
/// </summary>
/// <param name="Num">2字节Short</param>
public void PushUInt16(UInt16 Num)
{
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0xff00) >> 8) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)((Num & 0x00ff) & 0xff);
}
/// <summary>
/// 向ByteBuffer压入一个无符Int值
/// </summary>
/// <param name="Num">4字节UInt32</param>
public void PushInt(UInt32 Num)
{
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0xff000000) >> 24) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0x00ff0000) >> 16) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0x0000ff00) >> 8) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)((Num & 0x000000ff) & 0xff);
}
/// <summary>
/// 向ByteBuffer压入一个Long值
/// </summary>
/// <param name="Num">4字节Long</param>
public void PushLong(long Num)
{
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0xff000000) >> 24) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0x00ff0000) >> 16) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)(((Num & 0x0000ff00) >> 8) & 0xff);
TEMP_BYTE_ARRAY[CURRENT_LENGTH++] = (byte)((Num & 0x000000ff) & 0xff);
}
/// <summary>
/// 从ByteBuffer的当前位置弹出一个Byte,并提升一位
/// </summary>
/// <returns>1字节Byte</returns>
public byte PopByte()
{
byte ret = TEMP_BYTE_ARRAY[CURRENT_POSITION++];
return ret;
}
/// <summary>
/// 从ByteBuffer的当前位置弹出一个Short,并提升两位
/// </summary>
/// <returns>2字节Short</returns>
public UInt16 PopUInt16()
{
//溢出
if (CURRENT_POSITION + 1 >= CURRENT_LENGTH)
{
return 0;
}
UInt16 ret = (UInt16)(TEMP_BYTE_ARRAY[CURRENT_POSITION] << 8 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 1]);
CURRENT_POSITION += 2;
return ret;
}
/// <summary>
/// 从ByteBuffer的当前位置弹出一个uint,并提升4位
/// </summary>
/// <returns>4字节UInt</returns>
public uint PopUInt()
{
if (CURRENT_POSITION + 3 >= CURRENT_LENGTH)
return 0;
uint ret = (uint)(TEMP_BYTE_ARRAY[CURRENT_POSITION] << 24 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 1] << 16 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 2] << 8 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 3]);
CURRENT_POSITION += 4;
return ret;
}
/// <summary>
/// 从ByteBuffer的当前位置弹出一个long,并提升4位
/// </summary>
/// <returns>4字节Long</returns>
public long PopLong()
{
if (CURRENT_POSITION + 3 >= CURRENT_LENGTH)
return 0;
long ret = (long)(TEMP_BYTE_ARRAY[CURRENT_POSITION] << 24 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 1] << 16 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 2] << 8 | TEMP_BYTE_ARRAY[CURRENT_POSITION + 3]);
CURRENT_POSITION += 4;
return ret;
}
/// <summary>
/// 从ByteBuffer的当前位置弹出长度为Length的Byte数组,提升Length位
/// </summary>
/// <param name="Length">数组长度</param>
/// <returns>Length长度的byte数组</returns>
public byte[] PopByteArray(int Length)
{
//溢出
if (CURRENT_POSITION + Length >= CURRENT_LENGTH)
{
return new byte[0];
}
byte[] ret = new byte[Length];
Array.Copy(TEMP_BYTE_ARRAY, CURRENT_POSITION, ret, 0, Length);
//提升位置
CURRENT_POSITION += Length;
return ret;
}
}
}
由于实际需要我是要从byteArray中从左到右取数据,所以才定义了一个CURRENT_POSITION的变量,如果需要从右到左弹数据并减小Buffer的长度则直接用 --CURRENT_LENGTH就可以了