在寫網絡程序的時候,經常需要往一個數組裏面壓數據或者取數據,而Java中再Java.nio中有個ByteBuffer能很方便的實現,Delphi中也有個Stream類有着同樣的功能,這裏我就模仿JAVA用C#做個最基礎的ByteBuffer類
下面是代碼
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就可以了