我需要将 .NET 中生成的 Guid 传递给 Java 应用程序。我使用 Guid.ToByteArray() 将其作为 byte[] 存储在磁盘上,然后将其读入 Java 并将其转换为 UUID。为此,我复制了采用 byte[]
的 UUID 的(私有)构造函数的实现:
private UUID(byte[] data) {
long msb = 0;
long lsb = 0;
assert data.length == 16;
for (int i=0; i<8; i++)
msb = (msb << 8) | (data[i] & 0xff);
for (int i=8; i<16; i++)
lsb = (lsb << 8) | (data[i] & 0xff);
this.mostSigBits = msb;
this.leastSigBits = lsb;
}
但是,当我使用 toString()
检查 UUID 时,Java UUID 与 .NET Guid 不同。
例如,.NET Guid
888794c2-65ce-4de1-aa15-75a11342bc63
变成了 Java UUID,
c2948788-ce65-e14d-aa15-75a11342bc63
看起来前三组的字节顺序颠倒了,而后两组的顺序是相同的。
由于我希望 Guid 和 UUID 的 toString()
产生相同的结果,有谁知道我应该如何正确地将 .NET Guid 读入 Java UUID?
编辑:澄清一下,实施不是我自己的。它是 java.util.UUID
类的私有构造函数,它采用 byte[]
,我将其复制以用于从磁盘读取 byte[]转换为 UUID。
我不想使用字符串来存储指南,因为我存储了很多指南,这似乎浪费空间。
Russell Troywest 的链接至少澄清了为什么 Guid 的前几组结果相反,而后半部分保持相同的顺序。问题是,我可以依赖 .NET 始终 以相同的顺序生成这些字节吗?
I need to communicate a Guid that was generated in .NET to a Java application. I use Guid.ToByteArray()
to store it on disk as a byte[]
, then read it into Java and convert it to a UUID. For this purpose I copied the implementation of the (private) constructor of UUID that takes a byte[]
:
private UUID(byte[] data) {
long msb = 0;
long lsb = 0;
assert data.length == 16;
for (int i=0; i<8; i++)
msb = (msb << 8) | (data[i] & 0xff);
for (int i=8; i<16; i++)
lsb = (lsb << 8) | (data[i] & 0xff);
this.mostSigBits = msb;
this.leastSigBits = lsb;
}
However, when I inspect the UUID using toString()
, the Java UUID is different from the .NET Guid.
For example, the .NET Guid
888794c2-65ce-4de1-aa15-75a11342bc63
turns into the Java UUID
c2948788-ce65-e14d-aa15-75a11342bc63
It seems that the byte ordering of the first three groups is reversed, while the ordering in the last two groups is the same.
Since I would expect the toString()
of both the Guid and the UUID to yield the same result, does anyone know how I should correctly read the .NET Guid into a Java UUID?
Edit: To clarify, the implementation is not my own. It is the private constructor of the java.util.UUID
class that takes a byte[]
, which I copied to use for the purpose of reading a byte[] from disk into a UUID.
I do not want to use strings to store the Guids as I'm storing a lot of them and it seems like a waste of space.
Russell Troywest's link at least clarifies why the first couple of groups of the Guid come out reversed, while the second half stays in the same order. The question is, can I depend on .NET always generating these bytes in the same order?
发布评论
评论(9)
您不能将 .Net Guid 存储为字符串并将其读入 Java 中吗?这样你就不需要担心字节顺序或任何事情。
如果不是,那么这解释了 C# 中字节的布局方式
http://msdn。 microsoft.com/en-us/library/fx22893a.aspx
Could you not just store the .Net Guid as a string and read it into Java? That way you don't need to worry about byte order or anything.
If not then This explains how the bytes are laid out in C#
http://msdn.microsoft.com/en-us/library/fx22893a.aspx
编辑 2017-08-30:每个评论交换了数组元素 6 和 7。
我必须阅读&在 C# 应用程序中将 Guid 写入 MySQL(存储为二进制 (16)),但 Java 应用程序也使用该数据库。以下是我用于在 .NET 小端字节顺序和 Java 大端字节顺序之间转换的扩展方法:
Edit 2017-08-30: Swapped array elements 6 and 7 per comments.
I have to read & write Guids from/to MySQL (stored as binary(16)) in a C# app, but the database is also used by Java apps. Here are the extension methods I use for converting between .NET little-endian and Java big-endian byte order:
如前所述,.NET 中 GUID 的二进制编码在前三组中以小端顺序(相反)放置字节 - 请参阅 Guid.ToByteArray 方法。要从中创建 java.util.UUID ,您可以使用以下代码:
As already noted, the binary encoding of GUID in .NET has bytes in the first three groups placed in the little-endian order (reversed) – see Guid.ToByteArray Method. To create
java.util.UUID
from it you can use the following code:根据您的编辑,不,您不能始终依赖以相同顺序生成的字节。运行时决定字节顺序。然而,出于这个原因,C# 确实提供了
BitConverter.isLittleEndian
。我知道你无法改变 Java 实现的字节顺序和位移位。但您可以在存储之后、将它们发送到 Java 之前在 C# 端移动这些位。
更新:
有关 IsLittleEndian 的 MSDN 文章
编辑:
实际上,您可能可以指望它在第一个字节块的布局中始终是小尾数,但从技术上讲您不能。
In response to your edit, no, you cannot consistently depend on the bytes being generated in the same order. The runtime determines the endianness. C# does however offer
BitConverter.isLittleEndian
for this very reason.I know you can't change the endianness of the Java implementation and the bit shifting. But you can shift the bits on the C# end after storing and before sending them to Java.
Update:
MSDN Article on IsLittleEndian
Edit:
To be practical, you can PROBABLY count on it always being little endian in its layout of the first chunk of bytes, but technically you can't.
GUID.toByteArray 在 C# 中相当奇怪。前半部分采用小端格式,后半部分采用大端格式。
此页面上的评论指出了这一事实:
http://msdn.microsoft.com/en-us/库/system.guid.tobytearray.aspx
The GUID.toByteArray is pretty odd in C#. The first half are in little-endian and the second half are in big-endia.
A comment on this page notes this fact:
http://msdn.microsoft.com/en-us/library/system.guid.tobytearray.aspx
我认为你的问题是 .NET 是小端字节序,但 JAVA 是大端字节序,因此,当您从 JAVA 应用程序读取由 C# 应用程序编写的 128 位整数(GUID)时,您必须进行从小端到大端的转换。
I think your problem here is that .NET is little-endian but JAVA is big-endian, so when you read a 128 bits integer (a GUID) written by a C# app from a JAVA app you have to do de conversion from little-endian to big-endian.
编解码器
DotNetGuid1Codec
和DotNetGuid4Codec
可以将 UUID 编码为 .Net Guid。请参阅:uuid-creator
The codecs
DotNetGuid1Codec
andDotNetGuid4Codec
can encode UUIDs to .Net Guids.See: uuid-creator
这段代码对我有用。
This code works for me.
使用simd加速版本
Use simd accelerated version