如何将Long转换为Guid和Vice Versa?

时间:2010-10-10 14:30:30

标签: language-agnostic guid long-integer

这甚至可能吗?我甚至都不认为,但是我看到了一些尝试这样做的代码。但是,我的单元测试表明它无法正常工作。我确实看到了类似的想法:

只是为了澄清。 Guid创作超出了我的控制范围;因此,我不能将值存储在其中一个Guid集中。

6 个答案:

答案 0 :(得分:15)

  

GUID永远不会长,因为,   正如我所说,GUID的大小是16个字节,   长的大小是8个字节。您   高兴地丢掉了8个字节   GUID,即使它们是零! : - )

Guid只是一个128位数据结构,long是一个64位数据结构......

这意味着只要高64位为零,我们就可以安全地丢弃它们,稍后重建它们,因为在这种情况下,零不代表完整数据。所以是的,它是数据丢失,但在某些情况下,它是可以重建的数据丢失。 (考虑压缩)

当你说:

时,这没有什么不同
long x = 5000;
//Converting 64 bit data structure into a 32 bit, discarding the upper 32 bits.
int y = (int)x;
//Converting 32 bit data structure into a 64 bit.
long z = (long)y;

这些显式转换不会内置到系统中,因为它不是必须以不同方式进行的。

public static Guid ToGuid(long value)
{
    byte[] guidData = new byte[16];
    Array.Copy(BitConverter.GetBytes(value), guidData, 8);
    return new Guid(guidData);
}

public static long ToLong(Guid guid)
{
    if (BitConverter.ToInt64(guid.ToByteArray(), 8) != 0)
        throw new OverflowException("Value was either too large or too small for an Int64.");
    return BitConverter.ToInt64(guid.ToByteArray(), 0);
}

显然,这绝不应该与GUID一起使用,但只要GUID只有64位的“实际数据”就可以安全使用,最好的方法是确保永远不要在GUID上使用它,除非它们在哪里用很长的时间创建。

作为预防措施,我已经添加了抛出OverflowException,以防Guid在最后64位中实际存储除了0'之外的所有内容,因为生成的long将无法转换回相同的Guid。

所以......

  

只要创建的guid适合   这很长,有可能吗?它的   只是当它超过了长期的时候   指定大小。正确的吗?

是真的......显然GUID的相应长值不容易阅读,这里有一些例子(long = guid):

1.340 = 0000053c-0000-0000-0000-000000000000
98.605 = 0001812d-0000-0000-0000-000000000000
149.957 = 000249c5-0000-0000-0000-000000000000
218.125.225 = 0d0053a9-0000-0000-0000-000000000000
4.249.596.910 = fd4bb3ee-0000-0000-0000-000000000000
23.139.913.545 = 633f0f49-0005-0000-0000-000000000000
9.223.372.036.854.775.807 = ffffffff-ffff-7fff-0000-000000000000
-9.223.372.036.854.775.808 = 00000000-0000-8000-0000-000000000000
-1 = ffffffff-ffff-ffff-0000-000000000000

是的,那些转换既可以双向运作,也可以考虑任何长期价值......

但是因为你声明:

  

Guid的创作超出了我的控制范围。

你实际上做这件事的可能性极小,相反,你所拥有的Guid最有可能是用任何常用算法生成的,这会使Guid在这种情况下无法使用。


现在这样做有什么意义吗?......这需要洞察特定情况,并且是另一个讨论...

答案 1 :(得分:9)

GUID长度为16个字节。 “长”通常被理解为64位(即8字节)长。您无法在不丢失或提供额外数据的情况下进行转换。

答案 2 :(得分:1)

我知道这个问题真的很旧,但它是第一个Google结果,我想提供我的答案。

Guid不是其他人已经说过的Int64,而是它的两个UInt64。

我写了一个UInt128类,有一个高,一个低UInt64。从那里你需要在这些之间进行转换:

    public static UInt128 ToUInt128(this Guid g)
    {
        var array = g.ToByteArray();
        var hi = BitConverter.ToUInt64(array, 8);
        var lo = BitConverter.ToUInt64(array, 0);
        return new UInt128(hi, lo);
    }

    public static Guid ToGuid(this UInt128 i)
    {
        byte[] data = new byte[16];
        Array.Copy(BitConverter.GetBytes(i.hi), 0, data, 8, 8);
        Array.Copy(BitConverter.GetBytes(i.lo), 0, data, 0, 8);
        return new Guid(data);
    }

也许对某人有帮助!

答案 3 :(得分:0)

您可以使用Guid构造函数,这是一个简单但不完美的示例:

Guid g1;
long g2;

// {00000001-0000-0000-0000-000000000000}
g1 = new Guid(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

// 00000001
g2 = Convert.ToInt64(g1.ToString().Split('-')[0]);

// 1 + 5 = 6
g2 += 5;

// {00000006-0000-0000-0000-000000000000}
g1 = new Guid((uint)g2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

第一组最多可以处理4294967295(int)。如果你需要更多,那么你必须使用另一套。

每个集合都是无符号整数的十六进制表示,因此您可以使用各种可能性。

答案 4 :(得分:0)

public static Guid ToGuid(long value)
{
    byte[] bytes = new byte[16];
    BitConverter.GetBytes(value).CopyTo(bytes, 0);
    return new Guid(bytes);
}

希望,这段代码可以为您提供帮助!

答案 5 :(得分:0)

只要您必须使用不超过 Guid 大小的正整数值进行操作,您就可以像这样将数字转换为 Guid:

var guid = new Guid(ulong.MaxValue.ToString("00000000-0000-0000-0000-000000000000"));

并将其转换回:

var uint64 = Convert.ToUInt64(guid.ToString("N"))

在其他情况下,最好使用上面提到的字节转换。可以在此处查看示例:https://dotnetfiddle.net/Zx7faI