【问题标题】:Converting UUID to OID, translating java code to C# - how does this work?将 UUID 转换为 OID,将 java 代码转换为 C# - 这是如何工作的?
【发布时间】:2015-07-31 17:25:44
【问题描述】:

我正在尝试将此代码 (from David Clunie) 转换为 C#,以便在我的程序中从 UUID(或 GUID)创建 OID

public static String createOIDFromUUIDCanonicalHexString(String hexString) throws IllegalArgumentException {
        UUID uuid = UUID.fromString(hexString);
        long leastSignificantBits = uuid.getLeastSignificantBits();
        long mostSignificantBits  = uuid.getMostSignificantBits();
        BigInteger decimalValue = makeBigIntegerFromUnsignedLong(mostSignificantBits);
        decimalValue = decimalValue.shiftLeft(64);
        BigInteger bigValueOfLeastSignificantBits = makeBigIntegerFromUnsignedLong(leastSignificantBits);
        decimalValue = decimalValue.or(bigValueOfLeastSignificantBits);   // not add() ... do not want to introduce question of signedness of long
        return OID_PREFIX+"."+decimalValue.toString();

我不明白为什么要从 UUID 的各个部分生成 long(leastSignificantBits、mostSignificantBits),然后从它们生成 bigint - 为什么不直接生成 BigInt? (因为他无论如何都要把最重要的数字左移)。

谁能告诉我为什么要这样写? (免责声明:我没有尝试运行 java 代码,我只是想在 C# 中实现它)

[编辑]

原来有几个问题 - 正如 Kevin Coulombe 指出的那样,一个很大的问题是 Microsoft 存储 GUID 的字节顺序。java 代码似乎以明显的(从左到右)顺序获取字节,但有两个显然是分开的块(也感谢 Kevin),因为在 Java 中没有简单的方法来获取整个字节数组。

这是工作 C# 代码,向前和(部分)向后:

    class Program
{
    const string OidPrefix = "2.25.";

    static void Main(string[] args)
    {
        Guid guid = new Guid("000000FF-0000-0000-0000-000000000000");
        //Guid guid = new Guid("f81d4fae-7dec-11d0-a765-00a0c91e6bf6");
        Console.WriteLine("Original guid: " + guid.ToString());
        byte[] guidBytes = StringToByteArray(guid.ToString().Replace("-", ""));
        BigInteger decimalValue = new BigInteger(guidBytes);
        Console.WriteLine("The OID is " + OidPrefix + decimalValue.ToString());
        string hexGuid = decimalValue.ToHexString().PadLeft(32, '0');//padded for later use
        Console.WriteLine("The hex value of the big int is " + hexGuid);
        Guid testGuid = new Guid(hexGuid);
        Console.WriteLine("This guid should match the orginal one: " + testGuid);
        Console.ReadKey();
    }

    public static byte[] StringToByteArray(String hex)
    {
        int NumberChars = hex.Length;
        byte[] bytes = new byte[NumberChars / 2];
        for (int i = 0; i < NumberChars; i += 2)
            bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
        return bytes;
    }
}

【问题讨论】:

标签: c# java


【解决方案1】:

我认为他们这样做是因为没有简单的方法将 UUID 转换为字节数组以传递给 Java 中的 BigInteger。

看到这个:GUID to ByteArray

在 C# 中,这应该是您正在寻找的内容:

String oid = "prefix" + "." + new System.Numerics.BigInteger(
        System.Guid.NewGuid().ToByteArray()).ToString();

【讨论】:

  • 嗯...也许,但这会产生与使用 java 代码给出的示例不同的结果...我认为与 GUID 的 ToByteArray 方法相比,java 的 getLeastSignificantBits / getMostSignificantBits 的工作方式有所不同。例如, (new Guid("000000FF-0000-0000-0000-000000000000")).ToByteArray() 给我 {255,0,0,0,0,0,0...} 但如果我把 FF在第一个位置,我得到 {0,0,0,FF,0,0...}
  • 我不知道,但是 GUID 和 UUID 的存储方式不一定相同。它们按部分存储,但这些部分的字节顺序似乎需要解释:stackoverflow.com/questions/10190817/guid-byte-order-in-net
  • 这里直接来自微软的参考资料:“请注意,返回的字节数组中的字节顺序与 Guid 值的字符串表示不同。开始四字节组的顺序和接下来的两个两字节组颠倒,而最后一个两字节组和最后一个六字节组的顺序相同。” msdn.microsoft.com/en-us/library/system.guid.tobytearray.aspx
  • @KevinCoulombe - 谢谢,这就是我的发现。如果我采用 GUID 的字符串表示形式并手动将其解析(采用一对十六进制字符)到一个字节数组中,然后将其传递给 BigInt,我会得到与 Java 示例相同的结果。
【解决方案2】:
String oid_prefix = "2.25"
String hexString = "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
UUID uuid = UUID.fromString(hexString);
long leastSignificantBits = uuid.getLeastSignificantBits();
long mostSignificantBits  = uuid.getMostSignificantBits();
mostSignificantBits = mostSignificantBits & Long.MAX_VALUE;
BigInteger decimalValue = BigInteger.valueOf(mostSignificantBits);
decimalValue = decimalValue.setBit(63);
decimalValue = decimalValue.shiftLeft(64);
leastSignificantBits = leastSignificantBits & Long.MAX_VALUE;
BigInteger bigValueLeastSignificantBit = BigInteger.valueOf(leastSignificantBits);
bigValueLeastSignificantBit = bigValueLeastSignificantBit.setBit(63);
decimalValue = decimalValue.or(bigValueLeastSignificantBit);
println "oid is = "+oid_prefix+"."+decimalValue

【讨论】:

    猜你喜欢
    • 2021-05-19
    • 2013-07-12
    • 2016-04-14
    • 2014-05-27
    • 2015-09-27
    • 2020-01-20
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    相关资源
    最近更新 更多