C# 解析二进制数据,格式转换

    一.背景说明

   工作中经常遇到解析二进制文件,一般协议是由甲乙双方共同制定。因为项目周期长,变更总是无法避免;所以初始设计与实现可能存在偏差。

       1.统一的编码格式(ASCII 、Unicode、UTF8),未必统一

       2.不同语言,基本数据类型所占长度(int32、int64等),接收语言可变

       3.同一个地址值可变

    二.如何应对

     为了应对这样的不断迭代调整,需要配置设计灵活。解析结果往往是基本类型或者是一个对象,我以泛型代替

​
    public class UnitModel<T>where T:new()
    {
        public int startAdr { get; set; } //起地址
        public int index { get; set; } //位号
        public int length { get; set; } //字节长度
        public string order { get; set; } //顺序 "ABCD" "DCBA"
        public string orderBit { get; set; } //顺序 "AB" "BA"
        public string type { get; set; } //类型

        public string codetype { get; set; } //编码格式

        public T value { get; set; } //值

    }

   一个地址的解析通过上方来完成,本想写成枚举类型。

​
 public  class Decompose<T>
    {
        public UnitModel<T> Analyse(Byte[] bytes, UnitModel<T> t)
        {
            Byte[] bs = bytes.Skip(t.startAdr).Take(t.length).ToArray();

            bs = Order(bs, t);//字节顺序
            bs = OrderBit(bs, t);//字内bit顺序
            return Return(bs,t);  //字符串区分编码,类型不区分
        }

        private UnitModel<T> Return(Byte[] bs, UnitModel<T> t)
        {
            switch (t.type)
            {
                case "bit":
                    t.value = ReturnBit(bs, t);
                    return t;
                case "int":
                    t.value= ReturnInt32(bs, t);
                    return t;
                case "string":
                    t.value= ReturnString(bs, t);
                    return t;
                case "double":
                    t.value = ReturnDouble(bs, t);
                    return t;
                case "float":
                    t.value = ReturnDouble(bs, t);
                    return t;
            }
            return t;
        }

        private string ReturnString(byte[] bs, UnitModel<T> t)
        {
             switch (t.codetype)
         {
             case "ASCII":
                 return   Encoding.ASCII.GetString(bs);
             case "Unicode":
                 return Encoding.Unicode.GetString(bs);
             case "UTF8":
                 return Encoding.UTF8.GetString(bs);
         }
         return "";
        }

        /// <summary>
        /// 返回位
        /// </summary>
        /// <param name="bs"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        private bool ReturnBit(Byte[] bs, UnitModel<T> t)
        {
            string s ="";
            for (int i = 0;i < bs.Length; i++)
            {
                s += System.Convert.ToString(bs[i], 2).PadLeft(8, '0'); //!-- 先转换成二进制
            }
            if(s[t.index]==0)
            {
                return false;
            }
             return true;
        }

        /// <summary>
        /// 返回 int型
        /// </summary>
        /// <param name="bs"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        private int ReturnInt32(Byte[] bs, UnitModel<T> t)
        {
              switch (t.length)
            {
                case 4:
                    return BitConverter.ToInt32(bs, 0);
                case 2:
                    return ReturnInt32MakeUp(bs, t);
                case 1:
                    return ReturnInt32MakeUp(bs, t);
            }
            return 0;
        }

        /// <summary>
        /// 高位补O
        /// </summary>
        /// <param name="bs"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        private int ReturnInt32MakeUp(Byte[] bs, UnitModel<T> t)
        {
            byte[] byteArray = new byte[4];

            for (int m =0; m < t.length; m++)
            {
                byteArray[m] = bs[m];
            }
            return BitConverter.ToInt32(byteArray, 0);
        }

        /// <summary>
        /// 暂无3个字节的处理方式
        /// </summary>
        /// <param name="bs"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        private double ReturnDouble(Byte[] bs, UnitModel<T> t)
        {
            switch (t.length)
            {
                case 8:
                    return BitConverter.ToDouble(bs, 0);
                case 4:
                    return ReturnDoubleMakeUp(bs, t);
                case 1:
                    return Convert.ToDouble(bs[0]);
            }
            return 0;
        }

        /// <summary>
        /// float转double
        /// </summary>
        /// <param name="bs"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        private double ReturnDoubleMakeUp(Byte[] bs, UnitModel<T> t)
        {
            return  Convert.ToDouble( BitConverter.ToSingle (bs, 0));
        }


        /// <summary>
        /// 高低位的问题
        /// </summary>
        /// <param name="bs"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        private Byte[] OrderBit(Byte[] bs, UnitModel<T> t)
        {
            switch (t.codetype)
            {
                case "AB":
                    return bs;
                case "BA":
                    for (int i = 0; i < bs.Length; i++)
                    {
                        string s = System.Convert.ToString(bs[i], 2).PadLeft(8, '0'); //!-- 先转换成二进制
                        string tmpS = "";
                        for (int j = s.Length - 1; j < 0; j--)
                        {
                            tmpS += s[j];
                        }
                        bs[i] = System.Convert.ToByte(tmpS, 2);
                    }
                    return bs;
            }
            return null;
        }


        /// <summary>
        /// 顺序问题
        /// </summary>
        /// <param name="bs"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        private Byte[] Order(Byte[] bs, UnitModel<T> t)
        {
            switch (t.order)
            {
                case "ABCD":
                    return bs;
                case "DCBA":
                    Array.Reverse(bs);
                    return bs;
            }
            return null;
        }



    }

​

一个地址对应一个Model<T>,一个数据包分折成多个值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lyflcear

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值