数据包格式如下所示
$HEHDT,0.000,T*2F
$PIXSE,ATITUD,0.000,0.000*62
$PHROT,-0.001,0.003,0.002*7E
$PIXSE,IMU,0.029,0.044,9.792,0.000*24
$PIXSE,POSITI,36.66180000,114.56460000,0.000*58
$PIXSE,BDVEL_,0.000,0.000,0.000*7F
$PIXSE,SPEED_,0.000,0.000,0.000*61
$PIXSE,STATE,000023.50,00,00,00,A*6B
包体有$开头以\r结束,这是一个区间的数据包,也可以使用结束符适配器处理(下期说)
/// <summary>
/// 区间适配器
/// </summary>
public class BetweenAndDataReceiveAdapter
{
private readonly BoyerMoore _startBoyerMoore;
private readonly BoyerMoore _endBoyerMoore;
public List<byte> Data { get; set; }public event Action<byte[]> ParseRequestBodyEvent;
public BetweenAndDataReceiveAdapter(byte[] start, byte[] end)
{
_startBoyerMoore = new BoyerMoore(start);
_endBoyerMoore = new BoyerMoore(end);
Data = new List<byte>();
}/// <summary>
/// 收到消息
/// </summary>
/// <param name="data"></param>
public void ReceiveData(byte[] data)
{
Data.AddRange(data);
if (Data.Count > data.Length)
{
data = Data.ToArray();
}
var startLength = _startBoyerMoore.PatternLength;
var endLength = _endBoyerMoore.PatternLength;
var lastPosition = 0;
do
{
// 长度不够一个包等下次再来
if (data.Length - lastPosition < startLength + endLength)
{
break;
}// 搜索起始标志
var startPosition = _startBoyerMoore.Search(data, lastPosition);// 是否找到了
if (startPosition == -1)
{
break;
}startPosition = lastPosition + startPosition + startLength;
// 搜索结束标志, 从起始位置+起始标志长度开始找
var count = _endBoyerMoore.Search(data, startPosition);
if (count == -1)
{
break;
}// 得到一条完整数据包
var bodyData = Data.GetRange(startPosition, count).ToArray();
lastPosition += count + startLength + endLength;// 包体解析对象从适配器子类中获取
ParseRequestBodyEvent?.Invoke(bodyData);// 下次继续解析
} while (true);
if (lastPosition > 0)
{
// 再移除已经读了的数据
Data.RemoveRange(0, lastPosition);
}
}
}public class BoyerMoore
{
private int[] _jumpTable;
private byte[] _pattern;
public int PatternLength { get; private set; }
public BoyerMoore()
{
}
public BoyerMoore(byte[] pattern)
{
_pattern = pattern;
_jumpTable = new int[256];
PatternLength = _pattern.Length;
for (var index = 0; index < 256; index++)
_jumpTable[index] = PatternLength;
for (var index = 0; index < PatternLength - 1; index++)
_jumpTable[_pattern[index]] = PatternLength - index - 1;
}
public void SetPattern(byte[] pattern)
{
_pattern = pattern;
_jumpTable = new int[256];
PatternLength = _pattern.Length;
for (var index = 0; index < 256; index++)
_jumpTable[index] = PatternLength;
for (var index = 0; index < PatternLength - 1; index++)
_jumpTable[_pattern[index]] = PatternLength - index - 1;
}
public unsafe int Search(byte[] searchArray, int startIndex = 0)
{
if (_pattern == null)
throw new Exception("Pattern has not been set.");
if (PatternLength > searchArray.Length)
throw new Exception("Search Pattern length exceeds search array length.");
var index = 0;
var limit = searchArray.Length - PatternLength;
var patternLengthMinusOne = PatternLength - 1;
fixed (byte* pointerToByteArray = searchArray)
{
var pointerToByteArrayStartingIndex = pointerToByteArray + startIndex;
fixed (byte* pointerToPattern = _pattern)
{
while (index <= limit)
{
var j = patternLengthMinusOne;
while (j >= 0 && pointerToPattern[j] == pointerToByteArrayStartingIndex[index + j])
j--;
if (j < 0)
return index;
index += Math.Max(_jumpTable[pointerToByteArrayStartingIndex[index + j]] - PatternLength + 1 + j, 1);
}
}
}
return -1;
}
public unsafe List<int> SearchAll(byte[] searchArray, int startIndex = 0)
{
var index = 0;
var limit = searchArray.Length - PatternLength;
var patternLengthMinusOne = PatternLength - 1;
var list = new List<int>();
fixed (byte* pointerToByteArray = searchArray)
{
var pointerToByteArrayStartingIndex = pointerToByteArray + startIndex;
fixed (byte* pointerToPattern = _pattern)
{
while (index <= limit)
{
var j = patternLengthMinusOne;
while (j >= 0 && pointerToPattern[j] == pointerToByteArrayStartingIndex[index + j])
j--;
if (j < 0)
list.Add(index);
index += Math.Max(_jumpTable[pointerToByteArrayStartingIndex[index + j]] - PatternLength + 1 + j, 1);
}
}
}
return list;
}
public int SuperSearch(byte[] searchArray, int nth, int start = 0)
{
var e = start;
var c = 0;
do
{
e = Search(searchArray, e);
if (e == -1)
return -1;
c++;
e++;
} while (c < nth);
return e - 1;
}
}internal class Program
{
static void Main(string[] args)
{
try
{
string start = "$";
string end = "\r";
BetweenAndDataReceiveAdapter betweenAndDataReceiveAdapter = new BetweenAndDataReceiveAdapter(Encoding.UTF8.GetBytes(start), Encoding.UTF8.GetBytes(end));
betweenAndDataReceiveAdapter.ParseRequestBodyEvent += BetweenAndDataReceiveAdapter_ParseRequestBodyEvent;
string context = File.ReadAllText("Text.txt");
byte[] bytes = Encoding.UTF8.GetBytes(context);
byte[] bytes1 = File.ReadAllBytes("Text.txt");
betweenAndDataReceiveAdapter.ReceiveData(bytes);
Console.ReadKey();}
catch (Exception)
{throw;
}
}private static void BetweenAndDataReceiveAdapter_ParseRequestBodyEvent(byte[] obj)
{
try
{
Console.WriteLine(Encoding.UTF8.GetString(obj));
}
catch (Exception)
{throw;
}}
}