我有一个 C# 字符串,它可以包含任何 Unicode 字符集,我想将其转换为该字符串的 UTF8 编码的十六进制表示形式,每个 Unicode 字符之间有一个空格,例如字符串“$£€𐍈 ” 将转换为输出字符串“24 C2A3 E282AC F0908D88”。但我不知道该怎么做。因为 C# 中的字符串是 UTF16,所以我不能只说
foreach (char entry in myString) { ... }
,因为 Unicode 字形可以用 1 或 2 个 char
表示,就像上面示例中最后一个字形的情况一样。
我觉得我需要以一个
byte[][]
结尾,它代表字符列表,每个字符都表示为确定字符的 UTF8 编码字节列表。然后我可以将这些字节转换为其十六进制表示形式,并在 Unicode 字符之间留有空格。
我怎样才能达到预期的输出?
Rune
结构并使用堆栈分配的中间缓冲区来最小化中间内存分配,如下所示:
public static class TextHelper
{
public static string ToUtf8HexValues(this string s)
{
Span<byte> span = stackalloc byte[6];
Span<char> charSpan = stackalloc char[3];
var sb = new StringBuilder();
foreach (var rune in s.EnumerateRunes())
{
if (sb.Length > 0)
sb.Append(' ');
for (int i = 0, length = rune.EncodeToUtf8(span); i < length; i++)
if (span[i].TryFormat(charSpan, out var n, "X"))
sb.Append(charSpan.Slice(0, n));
}
return sb.ToString();
}
}
备注:
Rune
是在.NET Core 3中引入的。这个结构体:
表示 Unicode 标量值([ U+0000..U+D7FF ],包含在内;或 [ U+E000..U+10FFFF ],包含在内)。
Byte.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider))
是在 .NET Core 2.1 中引入的,它允许将 Byte
格式化为固定长度 Span<char>
,而无需进行字符串分配。
演示小提琴这里。