【问题标题】:Function convert Hex String to BitArray C#函数将十六进制字符串转换为位数组 C#
【发布时间】:2011-05-15 06:14:27
【问题描述】:

我创建了以下函数,它将按要求执行(将 HEX 字符串转换为 BitArray)。我不确定函数的效率,但我现在的主要问题是 Convert.ToInt64 函数是 endian specific。当它被移植到备用芯片组时,我们将得到不同的结果(或异常)。那么谁能想到另一种方法来进行这种转换???

public BitArray convertHexToBitArray(string hexData)
    {
        string binary_values = "";
        BitArray binary_array;

            if (hexData.Length <= "FFFFFFFFFFFFFFFF".Length) // Max Int64
            {
                binary_values = Convert.ToString(Convert.ToInt64(hexData, 16), 2);
                binary_array = new BitArray(binary_values.Length);

                for (int i = 0; i < binary_array.Length; i++)
                {
                    if (binary_values[i] == '0')
                    {
                        binary_array[i] = false;
                    }
                    else
                    {
                        binary_array[i] = true;
                    }
                }
            }
   }

我删除了大部分错误/异常处理以保持它的大小,所以请原谅。

【问题讨论】:

  • “芯片组”不是 BigEndian,而是 CPU 内核。十六进制字符串也不是 BE,MSB 总是在左边。如果这样的 CPU 内核确实存在,那么它将运行具有 BE 版本的 BitConverter 的 .NET 版本。这个问题没什么意义。
  • 使用 C# mono 这个解决方案最终会被移植到 Linux / Unix / Solaris / Non-stop 和许多其他平台上。我们公司过去在使用 Convert 类时遇到过问题……信不信由你,这是真的。

标签: c# bitmap hex endianness bitarray


【解决方案1】:

这是一个简单的答案,应该适用于任意长度的字符串:

public static BitArray ConvertHexToBitArray(string hexData)
{
    if (hexData == null)
        return null; // or do something else, throw, ...

    BitArray ba = new BitArray(4 * hexData.Length);
    for (int i = 0; i < hexData.Length; i++)
    {
        byte b = byte.Parse(hexData[i].ToString(), NumberStyles.HexNumber);
        for (int j = 0; j < 4; j++)
        {
            ba.Set(i * 4 + j, (b & (1 << (3 - j))) != 0);
        }
    }
    return ba;
}

【讨论】:

  • 我从一位同事那里得到了一些帮助,我们想出了一个类似的解决方案。我不太擅长移位,但这看起来不错!
【解决方案2】:

试试这个:

var int64 = Int64.Parse(hexData, NumberStyles.HexNumber);
var bytes = BitConverter.GetBytes(int64);
var bitArray = new BitArray(bytes);

【讨论】:

  • 非常有帮助,需要迭代才能超过 16 字节标记,但您赢得的代码量最少 :)
【解决方案3】:

我还没有测试过这个(考虑它是伪代码),但它会很快:

    public static BitArray ConvertHexToBitArray(string hex)
    {
        Guard.AssertNotNullOrEmpty(hex, "hex");
        Guard.AssertHex(hex, "hex");

        var bits = new BitArray(hex.Length * 4);

        int pos = 0;

        foreach(char c in hex)
        {
            foreach(bool flag in LookupBits(c))
            {
                bits.Set(pos, flag);
                pos++;
            }
        }

        return bits;
    }

    private static readonly Dictionary<char, List<bool>> _hexVsBits = CreateHexLookupTable();

    private static Dictionary<char, List<bool>> CreateHexLookupTable()
    {
        var hexVsBits = new Dictionary<char, List<bool>>();

        hexVsBits.Add('0', CreateBitsArray(false, false, false, false));
        hexVsBits.Add('1', CreateBitsArray(false, false, false, true));
        hexVsBits.Add('2', CreateBitsArray(false, false, true, false));
        hexVsBits.Add('3', CreateBitsArray(false, false, true, true));
        hexVsBits.Add('4', CreateBitsArray(false, true, false, false));
        hexVsBits.Add('5', CreateBitsArray(false, true, false, true));
        hexVsBits.Add('6', CreateBitsArray(false, true, true, false));
        hexVsBits.Add('7', CreateBitsArray(false, true, true, true));

        // complete hex table

        return hexVsBits;
    }

    private static List<bool> CreateBitsArray(bool msb, bool msbMinusOne, bool lsbPlusOne, bool lsb)
    {
        var bits = new List<bool>(4);

        bits.Add(msb);
        bits.Add(msbMinusOne);
        bits.Add(lsbPlusOne);
        bits.Add(lsb);

        return bits;
    }

    private static IEnumerable<bool> LookupBits(char hexValue)
    {
        return _hexVsBits[hexValue];
    }
}

还有守卫:

public static class Guard
{
    public static void AssertHex(string value, string parameterName)
    {
        foreach(char entry in value)
        {
            if (!Char.IsNumber(entry))
            {
                if (entry != 'a' && entry != 'A' && entry != 'b' && entry != 'B' 
                    && entry != 'c' && entry != 'C' && entry != 'd' && entry != 'D' && entry != 'e' && entry != 'E' && entry != 'f' && entry != 'F')
                {
                    throw new ArgumentException("Not a valid hexidecimal number", parameterName);
                }
            }
        }
    }

    public static void AssertNotNullOrEmpty(string value, string parameterName)
    {
        if (string.IsNullOrEmpty(value))
            throw new ArgumentNullException(parameterName);
    }
}

【讨论】:

  • 我找不到对 Guard.AssertHex() 或 Guard.AssertNotNullOrEmpty() 的引用
  • 我可以给你写出来(我只是为了给你一个快速的答复而把守卫打断了)
  • 看起来不错,我最终得到了另一个未在此处发布的解决方案,但您赢得了最复杂的解决方案奖!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-17
  • 1970-01-01
  • 2017-08-12
  • 2018-01-31
  • 2019-03-07
  • 1970-01-01
  • 2019-06-08
相关资源
最近更新 更多