获取使用大端格式 C# 进行编码的 guid
Posted
技术标签:
【中文标题】获取使用大端格式 C# 进行编码的 guid【英文标题】:Get a guid to encode using big-endian formatting C# 【发布时间】:2018-06-17 06:39:41 【问题描述】:我有一个不寻常的情况,我有一个使用二进制 (16) 主键的现有 mysql 数据库,这些是现有 api 中使用的 UUID 的基础。
我的问题是我现在想添加一个用 dotnet core 编写的替换 api,我遇到了编码问题,已经解释了 here
具体来说,dotnet 中的 Guid 结构使用混合端格式,生成与现有 api 不同的字符串。由于显而易见的原因,这是不可接受的。
所以我的问题是:有没有一种优雅的方法可以强制 Guid 结构完全使用大端格式编码?
如果没有,我可以写一个糟糕的 hack,但我想我会先咨询 SO 社区的集体智慧!
【问题讨论】:
【参考方案1】:不;据我所知,没有内置的方法可以做到这一点。是的,Guid
目前有我只能称之为“crazy-endian”的实现。您需要获取Guid
-ordered 位(通过unsafe
或Guid.ToByteArray
),然后手动对它们进行排序,确定要反转哪些块 - 这不是简单的Array.Reverse()
。所以:恐怕非常手动。我建议使用类似的 guid
00010203-0405-0607-0809-0a0b0c0d0e0f
调试它;这给了你(我怀疑你知道):
03-02-01-00-05-04-07-06-08-09-0A-0B-0C-0D-0E-0F
所以:
反向4 反向2 反向2 直8【讨论】:
我担心可能是这种情况。这令人沮丧,因为虽然我不介意进行一些手动编码,但这会掩盖原本非常自我解释的代码。我想我只需要添加一些冗长的 cmets。不过感谢您的调试提示!【参考方案2】:截至 2021 年,仍然没有内置方法可以将 System.Guid
转换为 C# 中与 MySQL 兼容的大端字符串。
这是我们在工作中遇到这个确切的 C# 混合端 Guid 问题时想出的扩展:
public static string ToStringBigEndian(this Guid guid)
// allocate enough bytes to store Guid ASCII string
Span<byte> result = stackalloc byte[36];
// set all bytes to 0xFF (to be able to distinguish them from real data)
result.Fill(0xFF);
// get bytes from guid
Span<byte> buffer = stackalloc byte[16];
_ = guid.TryWriteBytes(buffer);
int skip = 0;
// iterate over guid bytes
for (int i = 0; i < buffer.Length; i++)
// indices 4, 6, 8 and 10 will contain a '-' delimiter character in the Guid string.
// --> leave space for those delimiters
if (i is 4 or 6 or 8 or 10)
skip++;
// stretch high and low bytes of every single byte into two bytes (skipping '-' delimiter characters)
result[(2 * i) + skip] = (byte)(buffer[i] >> 0x4);
result[(2 * i) + 1 + skip] = (byte)(buffer[i] & 0x0Fu);
// iterate over precomputed byte array.
// values 0x0 to 0xF are final hex values, but must be mapped to ASCII characters.
// value 0xFF is to be mapped to '-' delimiter character.
for (int i = 0; i < result.Length; i++)
// map bytes to ASCII values (a-f will be lowercase)
ref byte b = ref result[i];
b = b switch
0xFF => 0x2D, // Map 0xFF to '-' character
< 0xA => (byte)(b + 0x30u), // Map 0x0 - 0x9 to '0' - '9'
_ => (byte)(b + 0x57u) // Map 0xA - 0xF to 'a' - 'f'
;
// get string from ASCII encoded guid byte array
return Encoding.ASCII.GetString(result);
它有点长,但除了返回的大端字符串之外,它没有堆分配,所以它保证很快:)
【讨论】:
以上是关于获取使用大端格式 C# 进行编码的 guid的主要内容,如果未能解决你的问题,请参考以下文章