首页 > 代码库 > 用于拼包和解码的环形缓冲区类
用于拼包和解码的环形缓冲区类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test
{
/// <summary>
/// 环形缓冲区
/// </summary>
public class CRawBuffer
{
byte[] m_BufArr;
int m_i4BufLen; //数据缓冲区大小
public int m_i4ReadPos; //读游标
public int m_i4WritePos; //写游标
const int const_maxLen = 102400;
public CRawBuffer(int i4MaxQueueBufferSize)
{
m_BufArr = new byte[i4MaxQueueBufferSize];
if (i4MaxQueueBufferSize <= 0 || i4MaxQueueBufferSize > const_maxLen)
{
m_BufArr = new byte[const_maxLen];
m_i4BufLen = const_maxLen;
}
else
{
m_BufArr = new byte[i4MaxQueueBufferSize];
m_i4BufLen = i4MaxQueueBufferSize;
}
//m_BufArr.SetValue(0, 0, m_BufArr.Length - 1);
m_i4ReadPos = 0;
m_i4WritePos = 0;
}
public void SetRawDataToBuffer(byte[] byteArr, int nDataLen)
{
for (int i = 0; i < nDataLen; i++)
{
//接收的数据量达到缓冲区最大值,则将m_i4WritePos置0,从头开始计数(循环计数)
if (m_i4WritePos == m_i4BufLen)
{
m_i4WritePos = 0;
}
m_BufArr[m_i4WritePos] = byteArr[i];
m_i4WritePos++;//更新要写入数据位置
//接收的数据量达到缓冲区最大值,则将m_i4WritePos置0,从头开始计数(循环计数)
if (m_i4WritePos == m_i4BufLen)
{
m_i4WritePos = 0;
}
}
}
public void SetUsedLength(int i4Length)
{
//根据已经使用数据个数,移动开始标记指针
m_i4ReadPos = m_i4ReadPos + i4Length;
if (m_i4ReadPos >= m_i4BufLen)
m_i4ReadPos = m_i4ReadPos - m_i4BufLen;
}
public int GetData(byte[] byteArr, int i4Length)
{
int i4RealLength = 0;
int i4ReadPosEnd = m_i4WritePos;//固定数据末尾位置
if (i4ReadPosEnd > m_i4ReadPos)//正常情况,读数据的最新位置大于上次读完数据的位置,取出数据
{
i4RealLength = i4ReadPosEnd - m_i4ReadPos;//实际数据长度
if (i4RealLength >= i4Length)//实际数据长,要求获取数据短,这样就只给需要的长度数据
{
memcpy(byteArr, 0, m_BufArr, m_i4ReadPos, i4Length);
i4RealLength = i4Length;
}
else//要求获取数据比实际数据长
{
memcpy(byteArr, 0, m_BufArr, m_i4ReadPos, i4RealLength);
}
}
else if (i4ReadPosEnd < m_i4ReadPos)//越界情况,读数据的最新位置小于上次读完数据的位置,分两次拷贝数据
{
//检查缓冲区末尾长度是否够用m_i4BufLen
if (m_i4BufLen - m_i4ReadPos >= i4Length)//尾段够用
{
memcpy(byteArr, 0, m_BufArr, m_i4ReadPos, i4Length);
i4RealLength = i4Length;
}
else//必须跨段两次写入
{
//先读完缓冲区,再从缓冲区头部开始读数
memcpy(byteArr, 0, m_BufArr, m_i4ReadPos, m_i4BufLen - m_i4ReadPos);
i4RealLength = m_i4BufLen - m_i4ReadPos + i4ReadPosEnd;//实际数据长度
if (i4RealLength >= i4Length)//两段长度之和大于i4Length
{
memcpy(byteArr, m_i4BufLen - m_i4ReadPos, m_BufArr, 0, i4Length - (m_i4BufLen - m_i4ReadPos));
i4RealLength = i4Length;
}
else//两段长度之和小于i4Length
{
memcpy(byteArr, m_i4BufLen - m_i4ReadPos, m_BufArr, 0, i4ReadPosEnd);
}
}
}
else return 0;//i4ReadPosEnd 和 m_i4ReadPos 重叠
return i4RealLength;
}
private void memcpy(byte[] targetArr, int nTargetOffset, byte[] sourceArr, int nSourceOffset, int nDataLen)
{
for (int i = 0; i < nDataLen; i++)
{
targetArr[i + nTargetOffset] = sourceArr[i + nSourceOffset];
}
}
}
}
用于拼包和解码的环形缓冲区类