如何将.NET Guid读入Java UUID

时间:2011-04-21 14:31:24

标签: c# java .net guid uuid

我需要将在.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;
}

但是,当我使用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。

我不想使用字符串存储Guids,因为我存储了大量的Guids,这似乎是浪费空间。

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

8 个答案:

答案 0 :(得分:11)

你能不能将.Net Guid存储为字符串并将其读入Java?这样你就不必担心字节顺序或任何事情了。

如果没有那么这解释了如何在C#

中布置字节

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

答案 1 :(得分:11)

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

我必须阅读&amp;从/向MySQL编写Guid(存储为二进制(16))在C#应用程序中,但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);
    }
}

答案 2 :(得分:7)

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

我知道你不能改变Java实现的端点和位移。但是你可以在存储之后和发送到Java之前移位C#端的位。

更新

MSDN Article on IsLittleEndian

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

答案 3 :(得分:5)

GUID.toByteArray在C#中很奇怪。上半场是小端,下半场是大端。

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

  

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

答案 4 :(得分:4)

如前所述,.NET中GUID的二进制编码在前三个组中的字节中以小端顺序排列(反向) - 请参阅Guid.ToByteArray Method。要从中创建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());
}

答案 5 :(得分:2)

我认为你的问题是.NET is little-endian but JAVA is big-endian,所以当你读一个来自JAVA应用程序的C#应用​​程序编写的128位整数(一个GUID)时,你必须从little-endian转换为big- end-端。

答案 6 :(得分:0)

此代码适用于我。

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)

答案 7 :(得分:0)

UuidUtil中有一个方法可以在其他人需要的情况下进行此操作。

UUID uuid = UuidUtil.fromMssqlGuidToUuid(guid);

另一种方法则相反。

UUID guid = UuidUtil.fromUuidToMssqlGuid(uuid);

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