.NET 和 Linux 之间的 GUID/UUID 兼容性问题
GUID/UUID compatibility issue between .NET and Linux
在我的 c++ 程序中,我使用 debian Linux 的 uuid 包生成一个 uuid 值,它返回了一个大小为 16 的无符号 char 数组,它的类型为 uuid_t。然后我将其转换为字符串并将其打印到控制台。
然后我获取相同的字节数组,并通过网络将其发送到Windows机器。Windows 计算机使用 .net 的 GUID 类型,并使用相同的字节数组创建一个 GUID 对象。然后,我使用 GUID 的 ToString 方法再次将其打印到控制台。令人惊讶的是,相同的字节数组在 Linux 和 .Net 下具有不同的字符串表示形式,即使它们几乎相似。
下面是一个示例:
字节数组:
101,208,176,173,236,192,64,86,191,214,132,2,213,232,143,247
Linux:65d0b0ad-ecc0-4056-bfd6-8402d5e88ff7
。网:adb0d065-c0ec-5640-bfd6-8402d5e88ff7
您可能会注意到它们非常相似,最后一部分是相同的,第一部分使用相同的数字,只是数字的顺序不同。我按照上面解释的方式创建的每个UUID都遵循相同的模式,这让我认为存在字节顺序差异。
如何在 linux 中创建 UUID 值并使用相同的字节数组具有相同的字符串表示形式。
根据此消息和此消息,问题实际上在于对 GUID/UUID 应该是大端序还是小端序的不同理解。看起来Microsoft的实现将它们视为大端序(至少在英特尔平台上),但uuid_unparse
似乎是小端序。Wiki 说 GUID(这是Microsoft的 UUID)遵循 RFC 4122 第 4.1.2 节,这似乎要求大端序排序。
因此,这是实现之间的明显不一致。作为一种解决方法,我建议以字符串格式在系统之间交换数据,这在两个系统中似乎是一致的。
你不能使用相同的字节数组,并且Guid.ToString
生成与 Linux 字符串匹配的字符串。
您需要决定要优先考虑哪一个:
var dotNetGuid = new Guid(new byte[] { 101, 208, 176, 173, 236, 192, 64, 86,
191, 214, 132, 2, 213, 232, 143, 247 });
// option 1 - keep the existing guid's byte array intact
// and create a new ToUnixString method to display it as-required
Console.WriteLine(dotNetGuid.ToString()); // adb0d065-c0ec-5640-bfd6-8402d5e88ff7
Console.WriteLine(dotNetGuid.ToUnixString()); // 65d0b0ad-ecc0-4056-bfd6-8402d5e88ff7
// option 2 - create a new guid by re-arranging the existing guid's byte array
// and then use the standard ToString method
var unixGuid = dotNetGuid.ChangeByteOrder();
Console.WriteLine(dotNetGuid.ToString()); // adb0d065-c0ec-5640-bfd6-8402d5e88ff7
Console.WriteLine(unixGuid.ToString()); // 65d0b0ad-ecc0-4056-bfd6-8402d5e88ff7
// ...
public static class GuidExtensions
{
public static string ToUnixString(this Guid guid,
string format = "D", IFormatProvider provider = null)
{
return guid.ChangeByteOrder().ToString(format, provider);
}
public static Guid ChangeByteOrder(this Guid guid)
{
var s = guid.ToByteArray();
var d = new byte[]
{
s[3], s[2], s[1], s[0], s[5], s[4], s[7], s[6],
s[8], s[9], s[10], s[11], s[12], s[13], s[14], s[15]
};
return new Guid(d);
}
}
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 提升序列化 1:73 的向后兼容性问题
- 在 XSLT 1.0 中生成 UUID
- 在gcc中意外调用了Const重载.编译器错误或兼容性修复程序
- 各种版本的 Mac OSX 向后兼容性如何?(Xcode C++
- Visual Studio 19-17 库兼容性根据 GL 标志
- 致命错误:找不到'boost/uuid/uuid.hpp'文件
- C++ ABI 兼容性问题/张量流
- 查找蓝牙设备的服务的 uuid
- Oracle OCCI 和 g++ 7.1 的兼容性问题
- 为什么库API+编译器ABI足以确保具有不同版本gcc的对象之间的兼容性
- 对指针和恒常性兼容性的引用
- 检查操作系统兼容性
- 添加noexcept是否会破坏二进制兼容性
- 右值需要分配什么向后兼容性
- 如何在不添加对库的依赖的情况下添加与库结构的兼容性
- Generate boost::uuids::uuid from boost::compute::detail::sha
- 如何将 time-uuid(存储在 boost uuid 中)转换为时间戳/自纪元以来的时间?
- 在Qt中使用C++Lambda函数作为插槽是否有助于保持库的二进制兼容性?
- .NET 和 Linux 之间的 GUID/UUID 兼容性问题