为啥 .NET GUID 中有破折号?
Posted
技术标签:
【中文标题】为啥 .NET GUID 中有破折号?【英文标题】:Why are there dashes in a .NET GUID?为什么 .NET GUID 中有破折号? 【发布时间】:2011-04-03 05:04:16 【问题描述】:为什么 .NET GUID 中有破折号? GUID 的大多数实现中是否有破折号,或者它只是 Microsoft 的东西?
签名,
741ecf77-9c92-4435-8e6b-85975bd13452
【问题讨论】:
有趣的问题。我必须说我从来没有停下来思考过。 GUID 具有相同的熵,无论它们是否包含连字符。 连字符仅在显示为文本时使用。真正的 UUID 是一个 16 字节的二进制字符串/数组。 【参考方案1】:在 UUID(通用唯一标识符)规范的初始版本中,每个数据元素都有一个语义含义:
time_low - time_mid - time_high_and_version - clock_seq_and_reserved clock_seq_low - node_id
这些元素旨在提供时间(时间位)和空间(主机位)唯一性。
版本历史
由于发现在 2^1024 随机位的密钥空间中发生冲突的数学概率在天文数字上是不可能的,因此出于安全和隐私原因,UUID 规范的后续版本已逐步淘汰时间和主机数据。
唯一保留任何含义的元素是版本位和保留位。
版本 3 UUID 派生自 URI 或其他专有名称的 MD5 哈希。
第 4 版是使用随机数据生成的,目前是您在野外看到的最常见的实现。
版本 5 源自 SHA1 哈希。
存储格式
由于在 RFC 中为 UUID 的 ASCII 格式指定了连字符,即使各个部分不再保留其原始含义,如果您需要互操作性,它们仍然是必需的。
UUID 有时也存储为 base64 或 ascii85 编码字符串,以节省空间以通过非二进制安全的传输方式传输,并且不需要遵守 RFC。
ASCII:3F2504E0-4F89-11D3-9A0C-0305E82C3301 Base64:7QDBkvCA1+B9K/U0vrQx1A Ascii85: 5:$Hj:Pf\4RLB9%kU\Lj参考文献:RFC4122(UUID 格式的 ABNF 描述请参见第 3 页) ***GUIDUUID
【讨论】:
【参考方案2】:从技术上讲,GUID 中没有“破折号”。 GUID 是一个 128 位的值,通常以以下方式存储(此处使用 C# 表示结构):
public struct Guid
public ulong Data1;
public ushort Data2;
public ushort Data3;
public fixed byte Data4[8];
破折号在 GUID 的 字符串表示中。
破折号是可选的,在 GUID 的字符串表示中不是必需的。
也就是说,there are historical reasons as to where the placement of the dashes are,与 GUID 的生成方式有关,但该历史语义不再适用。
【讨论】:
这完全不正确,GUID的连字符ASCII十六进制表示中有5个连字符元素,包含二进制GUID元素的结构只有4个元素长。此外,历史语义肯定确实仍然适用,尤其是在这个问题中,考虑到历史是连字符首先出现的确切原因。 @joshperry 您已经从答案中重申了我的观点。Guid
只有 128 个字节,句号。分隔符来自representation。此外,关于应用于 representation 的历史语义,它们没有。正如你所说,这是出于历史原因。这些历史原因不再适用。根据您的回答,“这些数据元素不再具有任何特定含义。”
我不确定我在哪里重申 GUID 是 128 个字节,但是您的第二段(关于与结构对应的连字符)显然不准确。有连字符因为布局是在 UUID RFC 中指定的,并且与该结构无关。诚然,当代 UUID 中的片段并不一定意味着它们过去的含义,但是,由于它们过去的含义,它们存在。所以我猜他们现在在那里,因为 RFC 是这么说的,如果您想要/需要创建可互操作的 URN,那么您将遵循 RFC。
@joshperry 删除了关于短划线位置的部分,并保留了它们是可选的。这应该满足你的观点。【参考方案3】:
.NET 的Guid
类可识别多种不同格式:破折号作为分隔符、无分隔符、括号作为分隔符、括号作为分隔符、无分隔符等
【讨论】:
更正,Guid
不是一个类,它是一个值类型。【参考方案4】:
您可以获得各种格式的指南。
假设您使用的是 c#:
Guid guid = Guid.NewGuid();
Console.WriteLine(guid.ToString("N"))
63be6f7e4e564f0580229f958f492077
Console.WriteLine(guid.ToString("D"))
63be6f7e-4e56-4f05-8022-9f958f492077
Console.WriteLine(guid.ToString("B"))
63be6f7e-4e56-4f05-8022-9f958f492077
Console.WriteLine(guid.ToString("P"))
(63be6f7e-4e56-4f05-8022-9f958f492077)
【讨论】:
【参考方案5】:连字符对值的唯一性或随机性绝对没有影响。它们只是对 GUID 定义的保留,并在视觉上将构成 GUID 的数据的四个不同部分分开。
【讨论】:
【参考方案6】:GUID 实际上只是一个数字。连字符向您展示了各种组件是如何分解的,但实际上并不是数字的一部分。它就像一个 IP 地址——你可以存储一个 32 位的数字,也可以存储一个带有点的字符串,它们是等价的。
【讨论】:
【参考方案7】:连字符用于分隔每个数字
E93416C5-9377-4A1D-8390-7E57D439C9E7
Hex digits Description
8 Data1
4 Data2
4 Data3
4 Initial two bytes from Data4
12 Remaining six bytes from Data4
【讨论】:
【参考方案8】:如果您想在某处存储 guid,请将其存储为 16 字节的数组,而不是其文本表示形式。您将节省大量空间,并且不会出现连字符的问题。
【讨论】:
【参考方案9】:连字符表示 Guid 的字节结构。
typedef struct _GUID
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[8];
GUID;
为:
(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX)
您可能可以在保存之前剥离它们。至少在 .NET 中,Guid 类型的构造函数将从其字符串表示中初始化 Guid 变量,而不管连字符是否仍然存在或已删除。
【讨论】:
嗯,没错,但你不能以任何有意义的方式使用该结构的一部分,对吗? 但是为什么Data4
中的额外连字符?
看这里解释:en.wikipedia.org/wiki/Globally_unique_identifier【参考方案10】:
这只是为了方便。 GUID 由 16 个字节组成,以十六进制文本表示形式由 32 个字符组成。没有连字符的 GUID 更难被人类感知,也更难被识别为 GUID,而不是一些随机性质的 16 字节数字。
【讨论】:
【参考方案11】:我见过的几乎每一个 guid 的视觉表示都使用虚线格式。这对眼睛来说更容易。
【讨论】:
【参考方案12】:这是一个分块的例子,就像电话号码、信用卡号码等一样。
Here is a good Wikipedia article about it.
【讨论】:
【参考方案13】:这只是一种方便。
http://en.wikipedia.org/wiki/GUID
【讨论】:
以上是关于为啥 .NET GUID 中有破折号?的主要内容,如果未能解决你的问题,请参考以下文章