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>,一個數據包分折成多個值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章