将长字符串的二进制转换为十六进制 c#

18
我正在寻找一种将长字符串二进制转换为十六进制字符串的方法。 这个二进制字符串看起来像这样:"0110011010010111001001110101011100110100001101101000011001010110001101101011"。 我尝试使用
hex = String.Format("{0:X2}", Convert.ToUInt64(hex, 2));

但是如果二进制字符串的长度超过Uint64的范围,那么这种方法就行不通了。

有没有其他的方法可以将二进制字符串转换为十六进制?

谢谢


9
为什么您期望Convert.ToUInt64()能够处理一个表示值大于UInt64所能容纳的字符串? - Andrew Barber
11个回答

36

我刚写了这个东西,也许你可以把它作为起点...

public static string BinaryStringToHexString(string binary)
{
    if (string.IsNullOrEmpty(binary))
        return binary;

    StringBuilder result = new StringBuilder(binary.Length / 8 + 1);

    // TODO: check all 1's or 0's... throw otherwise

    int mod4Len = binary.Length % 8;
    if (mod4Len != 0)
    {
        // pad to length multiple of 8
        binary = binary.PadLeft(((binary.Length / 8) + 1) * 8, '0');
    }

    for (int i = 0; i < binary.Length; i += 8)
    {
        string eightBits = binary.Substring(i, 8);
        result.AppendFormat("{0:X2}", Convert.ToByte(eightBits, 2));
    }

    return result.ToString();
}

我认为 TODO 中的 "throw otherwise" 让我感到困惑。看到有 TODO 的答案对我来说似乎很奇怪。您能否解释一下?我不明白为什么在那些情况下这个方法需要抛出异常。另外,如果二进制为 null,则会发生空引用异常,但也许这是您的意图。在这些情况下,我可能会添加一个守卫语句来返回 null。谢谢! - masterwok
1
看到一个带有TODO的答案对我来说并不奇怪:-一点也不。我假设OP可以添加他们认为必要的任何保护措施。我无法看到他们的调用代码,也不知道他们的完整用例意图。当然,进行空值检查是明智的;我会添加一个... - Mitch Wheat

11

这可能对您有所帮助:

string HexConverted(string strBinary)
    {
        string strHex = Convert.ToInt32(strBinary,2).ToString("X");
        return strHex;
    }

12
这个问题涉及长度超过64位的字符串。 - Ben Voigt
如果与大型二进制字符串一起使用,将无法正常工作。 - ArnaldoRivera

6
Convert.ToInt32("1011", 2).ToString("X");

对于长度超过此限制的字符串,您可以将其简单地分成多个字节:

var binary = "0110011010010111001001110101011100110100001101101000011001010110001101101011";
var hex = string.Join(" ", 
            Enumerable.Range(0, binary.Length / 8)
            .Select(i => Convert.ToByte(binary.Substring(i * 8, 8), 2).ToString("X2")));

请问能否解释一下什么是“2”,即第二个参数? - Fazal
1
'2' 告诉 Convert.ToInt32 方法提供的字符串是基于 2 进制的。考虑将十六进制字符串 "AABBCC" 转换为 int(即 11189196):只需指定您的字符串是基于 16 进制的,如下所示:Convert.ToInt32("AABBCC", 16) - Alex McMillan
这个问题涉及到包含超过64位数字的字符串,所以你的解决方案不适用。 - Jesper
@ Jesper,已经添加了更多细节到答案中。感谢您指出这一点。 - Soroush Falahati

4

我想出了这种方法。虽然我是编程和C#的新手,但我希望你会喜欢它:

static string BinToHex(string bin)
{
    StringBuilder binary = new StringBuilder(bin);
    bool isNegative = false;
    if (binary[0] == '-')
    {
        isNegative = true;
        binary.Remove(0, 1);
    }

    for (int i = 0, length = binary.Length; i < (4 - length % 4) % 4; i++) //padding leading zeros
    {
        binary.Insert(0, '0');
    }

    StringBuilder hexadecimal = new StringBuilder();
    StringBuilder word = new StringBuilder("0000");
    for (int i = 0; i < binary.Length; i += 4)
    {
        for (int j = i; j < i + 4; j++)
        {
            word[j % 4] = binary[j];
        }

        switch (word.ToString())
        {
            case "0000": hexadecimal.Append('0'); break;
            case "0001": hexadecimal.Append('1'); break;
            case "0010": hexadecimal.Append('2'); break;
            case "0011": hexadecimal.Append('3'); break;
            case "0100": hexadecimal.Append('4'); break;
            case "0101": hexadecimal.Append('5'); break;
            case "0110": hexadecimal.Append('6'); break;
            case "0111": hexadecimal.Append('7'); break;
            case "1000": hexadecimal.Append('8'); break;
            case "1001": hexadecimal.Append('9'); break;
            case "1010": hexadecimal.Append('A'); break;
            case "1011": hexadecimal.Append('B'); break;
            case "1100": hexadecimal.Append('C'); break;
            case "1101": hexadecimal.Append('D'); break;
            case "1110": hexadecimal.Append('E'); break;
            case "1111": hexadecimal.Append('F'); break;
            default:
                return "Invalid number";
        }
    }

    if (isNegative)
    {
        hexadecimal.Insert(0, '-');
    }

    return hexadecimal.ToString();
}

1

考虑到四位可以用一个十六进制值表示,您可以简单地按照每四个一组进行转换,分别进行转换,这样值就不会改变。

string bin = "11110110";

int rest = bin.Length % 4;
if(rest != 0)
    bin = new string('0', 4-rest) + bin; //pad the length out to by divideable by 4

string output = "";

for(int i = 0; i <= bin.Length - 4; i +=4)
{
    output += string.Format("{0:X}", Convert.ToByte(bin.Substring(i, 4), 2));
}

1
如果您想迭代字符串中每个字节的十六进制表示,可以使用以下扩展。我将Mitch的答案与this结合在一起。
static class StringExtensions
{
    public static IEnumerable<string> ToHex(this String s) {
        if (s == null)
            throw new ArgumentNullException("s");

        int mod4Len = s.Length % 8;
        if (mod4Len != 0)
        {
            // pad to length multiple of 8
            s = s.PadLeft(((s.Length / 8) + 1) * 8, '0');
        }

        int numBitsInByte = 8;
        for (var i = 0; i < s.Length; i += numBitsInByte)
        {
            string eightBits = s.Substring(i, numBitsInByte);
            yield return string.Format("{0:X2}", Convert.ToByte(eightBits, 2));
        }
    }
}

例子:

string test = "0110011010010111001001110101011100110100001101101000011001010110001101101011";

foreach (var hexVal in test.ToHex())
{
    Console.WriteLine(hexVal);  
}

打印
06
69
72
75
73
43
68
65
63
6B

1
如果您使用的是.NET 4.0或更高版本,并且愿意使用System.Numerics.dll(用于BigInteger类),则以下解决方案可以很好地工作:
public static string ConvertBigBinaryToHex(string bigBinary)
{
    BigInteger bigInt = BigInteger.Zero;
    int exponent = 0;

    for (int i = bigBinary.Length - 1; i >= 0; i--, exponent++)
    {
        if (bigBinary[i] == '1')
            bigInt += BigInteger.Pow(2, exponent);
    }

    return bigInt.ToString("X");
}

0

考虑到四位可以用一个十六进制值表示,您可以简单地按照每四个一组进行转换,分别进行转换,这样值就不会改变。

string bin = "11110110";

int rest = bin.Length % 4;
bin = bin.PadLeft(rest, '0'); //pad the length out to by divideable by 4

string output = "";

for(int i = 0; i <= bin.Length - 4; i +=4)
{
    output += string.Format("{0:X}", Convert.ToByte(bin.Substring(i, 4), 2));
}

0
static string BinToHex(string bin)
{
    if (bin == null)
        throw new ArgumentNullException("bin");
    if (bin.Length % 8 != 0)
        throw new ArgumentException("The length must be a multiple of 8", "bin");

    var hex = Enumerable.Range(0, bin.Length / 8)
                     .Select(i => bin.Substring(8 * i, 8))
                     .Select(s => Convert.ToByte(s, 2))
                     .Select(b => b.ToString("x2"));
    return String.Join(null, hex);
}

0

使用LINQ

   string BinaryToHex(string binaryString)
            {
                var offset = 0;
                StringBuilder sb = new();
                
                while (offset < binaryString.Length)
                {
                    var nibble = binaryString
                        .Skip(offset)
                        .Take(4);

                    sb.Append($"{Convert.ToUInt32(nibble.toString()), 2):X}");
                    offset += 4;
                }

                return sb.ToString();

            }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接