程序园技术初心

字节数组格式化解析

2019-12-01  本文已影响0人  triplestudio

1. 一些实用工具方法

有足够便捷的工具方法,则在用代码表达思想时会变得如鱼得水,一气呵成!

public class ByteHelper
{
    public static string BytesToHexString(byte[] bytes)
    {
        return BytesToHexString(bytes, " ");
    }

    public static string BytesToHexString(byte[] bytes, string span)
    {
        StringBuilder sb = new StringBuilder(bytes.Length * (2 + span.Length));
        bool isFirst = true;
        foreach (byte b in bytes)
        {
            if (isFirst)
            {
                isFirst = false;
            }
            else
            {
                sb.Append(span);
            }
            sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').ToUpper());
        }
        return sb.ToString();
    }

    public static byte[] HexStringToBytes(string hexString)
    {
        hexString = hexString.Replace(" ", "");
        if ((hexString.Length % 2) != 0)
            hexString += " ";
        byte[] returnBytes = new byte[hexString.Length / 2];
        for (int i = 0; i < returnBytes.Length; i++)
            returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Replace(" ", ""), 16);
        return returnBytes;
    }

    /// <summary>
    /// 字节数组转整型
    /// </summary>
    /// <param name="bytes"></param>
    /// <returns></returns>
    public static int GetIntValue(byte[] bytes)
    {
        return Convert.ToInt32(GetLongValue(bytes));
    }

    public static uint GetUnsignedIntValue(byte[] bytes)
    {
        return Convert.ToUInt32(GetUnsingedLongValue(bytes));
    }

    /// <summary>
    /// 将整型按小端转换成指定长度的byte数组
    /// </summary>
    /// <param name="value"></param>
    /// <param name="len"></param>
    /// <returns></returns>
    public static byte[] IntToBytes(int value, int len)
    {
        byte[] bytes = new byte[len];
        string strHexValue = Convert.ToString(value, 16).PadLeft(len * 2, '0');
        for (int index = 0; index < len; index++)
        {
            bytes[index] = Convert.ToByte(strHexValue.Substring(strHexValue.Length - (index + 1) * 2, 2), 16);
        }
        return bytes;
    }

    public static byte[] SubBytes(byte[] bytes, int startIndex, int len)
    {
        if (startIndex + len > bytes.Length) len = bytes.Length - startIndex;

        byte[] subBytes = new byte[len];
        Array.Copy(bytes, startIndex, subBytes, 0, len);
        return subBytes;
    }

    # region 以长整型支持最多 8 个字节的整数转换

    /// <summary>
    /// 非 1,2,4,8 字节的其它字节转换
    /// </summary>
    /// <param name="bytes"></param>
    /// <returns></returns>
    public static long GetIrregularLongValue(byte[] bytes)
    {
        long value = 0; // 循环读取每个字节通过移位运算完成long的4个字节拼装
        for (int count = 0; count < bytes.Length; ++count)
        {

            int shift = count << 3;
            value |= ((long)0xff << shift) & ((long)bytes[count] << shift);
        }
        return value;
    }

    /// <summary>
    /// 只考虑小端(有符号)
    /// </summary>
    /// <param name="bytes"></param>
    /// <returns></returns>
    public static long GetLongValue(byte[] bytes)
    {
        if (bytes.Length == 1)
        {
            return (long)((sbyte)bytes[0]);
        }
        else if (bytes.Length == 2)
        {
            return (long)BitConverter.ToInt16(bytes, 0);
        }
        else if (bytes.Length == 4)
        {
            return (long)BitConverter.ToInt32(bytes, 0);
        }
        else if (bytes.Length == 8)
        {
            return (long)BitConverter.ToInt64(bytes, 0);
        }
        return GetIrregularLongValue(bytes);
    }

    /// <summary>
    /// 只考虑小端(无符号)
    /// </summary>
    /// <param name="bytes"></param>
    /// <returns></returns>
    public static ulong GetUnsingedLongValue(byte[] bytes)
    {
        if (bytes.Length == 1)
        {
            return (ulong)bytes[0];
        }
        else if (bytes.Length == 2)
        {
            return (ulong)BitConverter.ToUInt16(bytes, 0);
        }
        else if (bytes.Length == 4)
        {
            return (ulong)BitConverter.ToUInt32(bytes, 0);
        }
        else if (bytes.Length == 8)
        {
            return (ulong)BitConverter.ToUInt64(bytes, 0);
        }
        return (ulong)GetIrregularLongValue(bytes);
    }

    #endregion
}

2. 配置定义

通过配置来达到动态解析的目的。
配置项通过包括几个方面:
(1)控制解析的基础配置
(2)业务需要的必要配置
(3)其它扩展的配置(如样式控制等)

{
    "数据结构":[
        { "长度":4, "标签":"温度","类型":"浮点型","大小端":"大","单位":"℃" },
        { "长度":4, "标签":"湿度","类型":"浮点型","大小端":"大","单位":"%" },
        { "长度":4, "标签":"露点","类型":"浮点型","大小端":"大","单位":"℃" },
    ],
}

3. 解析数据

/// <summary>
/// 解析数据
/// 根据配置:"长度":2, "标签":"距离","类型":"整型","大小端":"大","单位":"m"
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static JObject ParseData(byte[] data)
{
    JObject result = new JObject();
    JArray values = new JArray();
    JArray items = GetStructConfig().Value<JArray>("数据结构");
    int startIndex = 0;
    foreach (JObject item in items)
    {
        if (startIndex >= data.Length) return null;

        JObject valueItem = new JObject(); 

        int len = item.Value<int>("长度");
        string label = item.Value<string>("标签");
        string type = item.Value<string>("类型");
        string begin = item.Value<string>("大小端");
        string unit = item.Value<string>("单位");

        valueItem["label"] = label;


        byte[] bs = ByteHelper.SubBytes(data, startIndex, len);
        if ("整型".Equals(type))
        {
            if ("大".Equals(begin))
            {
                Array.Reverse(bs);
            }
            valueItem["value"] = ByteHelper.GetIntValue(bs);
        }
        else if ("浮点型".Equals(type))
        {
            if ("大".Equals(begin))
            {
                Array.Reverse(bs);
            }
            valueItem["value"] = Math.Round(BitConverter.ToSingle(bs, 0), 2);
        }
        else if ("字符型".Equals(type))
        {
            valueItem["value"] = Encoding.Default.GetString(bs);
        }
        else
        {
            valueItem["value"] = ByteHelper.BytesToHexString(bs);
        }

        valueItem["label"] = label;
        valueItem["unit"] = unit;

        values.Add(valueItem);
        startIndex += len;
    }
    result["values"] = values;
    return result;
}
}
上一篇下一篇

猜你喜欢

热点阅读