如何将 .NET Guid 读入 Java UUID

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5745512/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 12:33:48  来源:igfitidea点击:

How to read a .NET Guid into a Java UUID

c#java.netguiduuid

提问by The Slicer

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[]:

我需要将在 .NET 中生成的 Guid 传达给 Java 应用程序。我曾经Guid.ToByteArray()将它作为 . 存储在磁盘上byte[],然后将其读入 Java 并将其转换为 UUID。为此,我复制了 UUID 的(私有)构造函数的实现,该构造函数采用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.

但是,当我使用 来检查 UUID 时toString(),Java UUID 与 .NET Guid 不同。

For example, the .NET Guid

例如,.NET Guid

888794c2-65ce-4de1-aa15-75a11342bc63

turns into the Java UUID

变成 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?

由于我希望toString()Guid 和 UUID 产生相同的结果,有谁知道我应该如何正确地将 .NET Guid 读入 Java UUID?

Edit:To clarify, the implementation is not my own. It is the private constructor of the java.util.UUIDclass that takes a byte[], which I copied to use for the purpose of reading a byte[] from disk into a UUID.

编辑:澄清一下,实现不是我自己的。它是类的私有构造函数,java.util.UUID它采用 a byte[],我将其复制以用于将字节 [] 从磁盘读取到 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.

我不想使用字符串来存储 Guid,因为我存储了很多它们,这似乎是在浪费空间。

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 alwaysgenerating these bytes in the same order?

Russell Troywest 的链接至少澄清了为什么 Guid 的前几组出现逆转,而下半场保持相同的顺序。问题是,我可以依赖 .NET总是以相同的顺序生成这些字节吗?

采纳答案by Doug Stephen

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.isLittleEndianfor this very reason.

响应您的编辑,不,您不能始终依赖以相同顺序生成的字节。运行时确定字节序。然而,C# 确实提供BitConverter.isLittleEndian了这个原因。

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.

我知道你不能改变 Java 实现的字节序和位移。但是您可以在存储之后和将它们发送到 Java 之前移动 C# 端的位。

Update:

更新:

MSDN Article on IsLittleEndian

关于 IsLittleEndian 的 MSDN 文章

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.

编辑:实际上,您可以指望它在第一个字节块的布局中始终是小端,但从技术上讲,您不能。

回答by Russell Troywest

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.

您不能将 .Net Guid 存储为字符串并将其读入 Java 吗?这样你就不需要担心字节顺序或任何东西。

If not then This explains how the bytes are laid out in C#

如果不是那么这解释了字节在 C# 中的布局

http://msdn.microsoft.com/en-us/library/fx22893a.aspx

http://msdn.microsoft.com/en-us/library/fx22893a.aspx

回答by Paul Smith

Edit 2017-08-30: Swapped array elements 6 and 7 per comments.

编辑 2017-08-30:每条评论交换数组元素 6 和 7。

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:

我必须在 C# 应用程序中从/向 MySQL(存储为二进制(16))读取和写入 Guid,但该数据库也被 Java 应用程序使用。以下是我用于在 .NET little-endian 和 Java big-endian 字节顺序之间转换的扩展方法:

public static class GuidExtensions
{
    /// <summary>
    /// A CLSCompliant method to convert a Java big-endian Guid to a .NET 
    /// little-endian Guid.
    /// The Guid Constructor (UInt32, UInt16, UInt16, Byte, Byte, Byte, Byte,
    ///  Byte, Byte, Byte, Byte) is not CLSCompliant.
    /// </summary>
    [CLSCompliant(true)]
    public static Guid ToLittleEndian(this Guid javaGuid) {
        byte[] net = new byte[16];
        byte[] java = javaGuid.ToByteArray();
        for (int i = 8; i < 16; i++) {
            net[i] = java[i];
        }
        net[3] = java[0];
        net[2] = java[1];
        net[1] = java[2];
        net[0] = java[3];
        net[5] = java[4];
        net[4] = java[5];
        net[6] = java[7];
        net[7] = java[6];
        return new Guid(net);
    }

    /// <summary>
    /// Converts little-endian .NET guids to big-endian Java guids:
    /// </summary>
    [CLSCompliant(true)]
    public static Guid ToBigEndian(this Guid netGuid) {
        byte[] java = new byte[16];
        byte[] net = netGuid.ToByteArray();
        for (int i = 8; i < 16; i++) {
            java[i] = net[i];
        }
        java[0] = net[3];
        java[1] = net[2];
        java[2] = net[1];
        java[3] = net[0];
        java[4] = net[5];
        java[5] = net[4];
        java[6] = net[7];
        java[7] = net[6];
        return new Guid(java);
    }
}

回答by UnclickableCharacter

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.UUIDfrom it you can use the following code:

如前所述,.NET 中 GUID 的二进制编码在前三组中的字节按小端顺序(颠倒)放置 - 请参阅Guid.ToByteArray 方法。要从中创建java.util.UUID,您可以使用以下代码:

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.UUID;

public UUID toUUID(byte[] binaryEncoding) {
    ByteBuffer source = ByteBuffer.wrap(binaryEncoding);
    ByteBuffer target = ByteBuffer.allocate(16).
        order(ByteOrder.LITTLE_ENDIAN).
        putInt(source.getInt()).
        putShort(source.getShort()).
        putShort(source.getShort()).
        order(ByteOrder.BIG_ENDIAN).
        putLong(source.getLong());
    target.rewind();
    return new UUID(target.getLong(), target.getLong());
}

回答by Joey

The GUID.toByteArray is pretty odd in C#. The first half are in little-endian and the second half are in big-endia.

GUID.toByteArray 在 C# 中很奇怪。前半部分是小端,后半部分是大端。

A comment on this page notes this fact: http://msdn.microsoft.com/en-us/library/system.guid.tobytearray.aspx

此页面上的评论指出了这一事实:http: //msdn.microsoft.com/en-us/library/system.guid.tobytearray.aspx

the order of bytes in the returned byte array is different from the string representation of a Guid value. The order of the beginning four-byte group and the next two two-byte groups is reversed, whereas the order of the last two-byte group and the closing six-byte group is the same.

返回的字节数组中的字节顺序与 Guid 值的字符串表示形式不同。开始的四字节组和接下来的两个两字节组的顺序相反,而最后的两字节组和结束的六字节组的顺序相同。

回答by Doliveras

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.

我认为您的问题是.NET 是小端但 JAVA 是大端,因此当您从 JAVA 应用程序读取由 C# 应用程序编写的 128 位整数(GUID)时,您必须从little-endian进行反转换字节序到大字节序。

回答by fabiolimace

There's a method in UuidUtilthat does that if someone else needs it.

UuidUtil如果其他人需要它,有一种方法可以做到这一点。

UUID uuid = UuidUtil.fromMssqlGuidToUuid(guid);

Another method does the reverse.

另一种方法正好相反。

UUID guid = UuidUtil.fromUuidToMssqlGuid(uuid);

https://github.com/f4b6a3/uuid-creator

https://github.com/f4b6a3/uuid-creator

回答by iron9light

This code works for me.

这段代码对我有用。

var msb: Long = 0
var lsb: Long = 0
for(i <- Seq(3, 2, 1, 0, 5, 4, 7, 6)) {
  msb = (msb << 8) | (data(i) & 0xFF)
}
for(i <- 8 until 16) {
  lsb = (lsb << 8) | (data(i) & 0xFF)
}
new UUID(msb, lsb)