C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C#十六进制转字符串

C#实现十六进制与字符串转换的技术解析

作者:加号3

在嵌入式开发、网络通信、数据解析等场景中,十六进制与字符串的相互转换是 C# 开发者最频繁遇到的基础操作之一,下面我们就来看看具体的实现方法吧

在嵌入式开发、网络通信、数据解析等场景中,十六进制与字符串的相互转换是 C# 开发者最频繁遇到的基础操作之一。这一看似简单的任务,实则涉及编码理论、内存布局、性能优化等多个深层技术维度。

一、问题本质:什么是"十六进制转字符串"

1. 两种截然不同的转换方向

方向 A:字节数组 → 十六进制文本

将二进制数据(如 0x48 0x65 0x6C 0x6C 0x6F)转换为可读的十六进制字符串(如 “48656C6C6F”)。这是日志输出、协议调试、数据校验时的核心需求。

方向 B:十六进制文本 → 字节数组

将字符串形式的数据(如 “FF03A7”)还原为原始字节。这是解析设备上报的 hex 报文、处理配置文件的常见场景。

2. 与"字符串编码"的根本区别

初学者常混淆十六进制转换与字符编码转换:

理解这一区别至关重要:十六进制字符串是数据的视图,而非数据的语义。

二、字节数组转十六进制字符串

1. 格式化风格选择

工业界存在多种输出风格,需根据场景选择:

2. 大小写敏感性

十六进制字母 A-F 的大小写在数值上等价,但在某些场景有约束:

3. 前导零处理

单字节值小于 16 时(如 0x05),必须输出两位 “05” 而非一位 “5”。遗漏前导零会导致解析歧义——“5A” 是一个字节还是两个字节 0x05 和 0x0A?

三、十六进制字符串转字节数组

1. 输入合法性校验

真实世界的输入从不干净,健壮的转换必须处理:

2. 切分策略

按每两个字符一组切分是最直觉的方式,但需注意:

四、代码实现

public static string ConvertBytesToString(byte[] bytes, int datalen)
{
  string msg = "";
  for (int i = 0; i < datalen; i++)
  {
      int value = Convert.ToInt32(bytes[i]);
      msg += String.Format("{0:X2} ", value);
  }
  return msg;
}

五、编码陷阱与常见误区

误区一:“十六进制字符串"就是"字符串”

开发者常将 “Hello” 直接当作十六进制文本处理,试图将其转换为字节数组。实际上 “Hello” 是字符序列,其十六进制表示应为 “48656C6C6F”(ASCII 编码下)。混淆"字符串内容"与"字符串的十六进制编码"会导致逻辑错误。

误区二:忽略编码层直接转 Hex

需求"将字符串转为十六进制"存在歧义:

误区三:大端序与小端序

多字节数据(如 ushort、uint)在内存中的字节排列顺序:

十六进制字符串通常按大端序书写(如 “1234” 表示值 0x1234),但字节数组可能是小端序。转换时必须显式指定字节序,跨平台或网络通信时尤其危险。

误区四:不可见字符的显示

字节值 0x00(空字符)、0x0A(换行)、0x0D(回车)等在文本编辑器中不可见或干扰显示。十六进制转换是诊断此类问题的唯一可靠手段——不要信任文本框的"空白"。

六、跨平台与兼容性

C# 转换结果需与 C++、Python、JavaScript 等交互时,必须对齐约定:

协议文档应明确指定格式规范,避免联调时的隐性 Bug。

七、调试与诊断技巧

1. 数据比对

当通信双方数据不一致时:

2. 性能剖析

使用 BenchmarkDotNet 量化不同实现方案:

3. 边界测试

八、知识扩展

在 C# 中实现十六进制(Hex)与字符串的相互转换,通常用于数据编码、加密、网络传输等场景。下面介绍几种常用且高效的方法。

1. 字符串 → 十六进制(String to Hex)

将字符串按照指定编码(如 UTF-8、Unicode)转换为对应的十六进制字符串。

方法一:使用 BitConverter + 字节数组

using System.Text;
public static string StringToHex(string input, Encoding encoding = null)
{
    if (string.IsNullOrEmpty(input)) return "";
    encoding ??= Encoding.UTF8;
    byte[] bytes = encoding.GetBytes(input);
    return BitConverter.ToString(bytes).Replace("-", "");
}

特点:简单明了,但 BitConverter.ToString 生成的格式带短横线,需要移除。性能尚可。

方法二:手动逐字节转换(性能最优)

public static string StringToHexFast(string input, Encoding encoding = null)
{
    if (string.IsNullOrEmpty(input)) return "";
    encoding ??= Encoding.UTF8;
    byte[] bytes = encoding.GetBytes(input);
    char[] hex = new char[bytes.Length * 2];
    for (int i = 0; i < bytes.Length; i++)
    {
        byte b = bytes[i];
        hex[i * 2] = GetHexValue(b >> 4);
        hex[i * 2 + 1] = GetHexValue(b & 0x0F);
    }
    return new string(hex);
}
private static char GetHexValue(int val) => (char)(val < 10 ? '0' + val : 'A' + (val - 10));

特点:直接拼接字符数组,无中间字符串开销,适合高频调用。

方法三:使用 Convert.ToHexString(.NET 5+)

public static string StringToHexDotNet(string input, Encoding encoding = null)
{
    if (string.IsNullOrEmpty(input)) return "";
    encoding ??= Encoding.UTF8;
    byte[] bytes = encoding.GetBytes(input);
    return Convert.ToHexString(bytes);
}

特点:.NET 5 及以上内置方法,简洁高效,推荐使用。

2. 十六进制 → 字符串(Hex to String)

将十六进制字符串还原为原始字符串,需要注意编码一致。

方法一:使用 Convert.FromHexString(.NET 5+)

public static string HexToString(string hex, Encoding encoding = null)
{
    if (string.IsNullOrEmpty(hex)) return "";
    encoding ??= Encoding.UTF8;
    byte[] bytes = Convert.FromHexString(hex);
    return encoding.GetString(bytes);
}

特点:最简洁,内置处理大小写和空白(会抛出异常)。

方法二:手动解析(兼容旧版本)

public static string HexToStringManual(string hex, Encoding encoding = null)
{
    if (string.IsNullOrEmpty(hex)) return "";
    encoding ??= Encoding.UTF8;
    // 移除可能存在的短横线或空格
    hex = hex.Replace("-", "").Replace(" ", "");
    if (hex.Length % 2 != 0)
        throw new ArgumentException("无效的十六进制字符串,长度必须是偶数。");
    byte[] bytes = new byte[hex.Length / 2];
    for (int i = 0; i < bytes.Length; i++)
    {
        bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
    }
    return encoding.GetString(bytes);
}

特点:兼容 .NET Framework,可自定义处理分隔符。

3. 完整示例:可配置编码和大小写

using System;
using System.Text;
public static class HexConverter
{
    // 字符串转十六进制(.NET 5+)
    public static string ToHex(string input, Encoding encoding = null, bool upperCase = true)
    {
        if (string.IsNullOrEmpty(input)) return "";
        encoding ??= Encoding.UTF8;
        byte[] bytes = encoding.GetBytes(input);
#if NET5_0_OR_GREATER
        string hex = Convert.ToHexString(bytes);
        return upperCase ? hex : hex.ToLower();
#else
        StringBuilder sb = new StringBuilder(bytes.Length * 2);
        foreach (byte b in bytes)
            sb.Append(b.ToString(upperCase ? "X2" : "x2"));
        return sb.ToString();
#endif
    }
    // 十六进制转字符串
    public static string FromHex(string hex, Encoding encoding = null)
    {
        if (string.IsNullOrEmpty(hex)) return "";
        encoding ??= Encoding.UTF8;
        hex = hex.Replace("-", "").Replace(" ", "");
#if NET5_0_OR_GREATER
        byte[] bytes = Convert.FromHexString(hex);
        return encoding.GetString(bytes);
#else
        if (hex.Length % 2 != 0)
            throw new ArgumentException("十六进制字符串长度必须为偶数。");
        byte[] bytes = new byte[hex.Length / 2];
        for (int i = 0; i < bytes.Length; i++)
            bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
        return encoding.GetString(bytes);
#endif
    }
}

使用示例

string original = "Hello 世界";
string hex = HexConverter.ToHex(original, Encoding.UTF8, false);
Console.WriteLine(hex); // 输出: 48656c6c6f20e4b896e7958c
string restored = HexConverter.FromHex(hex, Encoding.UTF8);
Console.WriteLine(restored); // 输出: Hello 世界

九、结语

十六进制与字符串的转换是软件开发中最基础的操作之一,却也是最容易因"看似简单"而被低估的环节。从编码理论的澄清,到内存布局的理解,再到高性能实现的权衡,每一个环节都影响着程序的健壮性与效率。在 C# 生态中,现代语言特性(Span、SIMD)为这一古老问题提供了新的解法,但技术的选择始终应服务于业务场景——对于配置文件的偶尔解析,简洁可读优先;对于每秒处理百万条报文的网关,零分配与向量化则是必选项。理解原理,方能游刃有余。

到此这篇关于C#实现十六进制与字符串转换的技术解析的文章就介绍到这了,更多相关C#十六进制转字符串内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文