C#数据包解析之区间数据处理适配器

数据包格式如下所示

$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;
            }

        }
    }

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值