如何将 Long 转换为 Guid,反之亦然?

发布于 2024-09-26 12:32:56 字数 422 浏览 0 评论 0原文

这可能吗?我什至不认为是这样,但我看到一些代码试图做到这一点。然而,我的单元测试表明它不起作用。我确实看到了一些类似的想法:

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

Is this even possible? I don't even think it is, but I saw some code that was trying to do it. However, my unit tests showed that it was not working. I did see some similar thoughts:

Just for clarification. The Guid creation is outside of my control; therefore, I can't just store the value in one of the Guid sets.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

寄居人 2024-10-03 12:32:56

GUID 永远无法容纳很长的内容,因为,
正如我所说,GUID 的大小是 16 个字节,
long 的大小是 8 个字节。你
cannoy 很高兴地丢弃 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 上使用它,除非它们是使用长的。

作为预防措施,我添加了在 Guid 实际上在最后 64 位中存储除 0 之外的任何内容的情况下抛出 OverflowException,因为生成的 long 无法转换回相同的 Guid。

所以就这样...

只要创建的指南适合
长了,可能吗?它是
就在它过去了长的时候
指定尺寸。对吗?

是的...显然,GUID 的相应长值不容易读取,这里有一些示例(长= 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 在这种情况下无法使用。


现在这样做有意义吗?...这需要对特定情况有深入的了解,并且是一个完全不同的讨论...

A GUID can never fit a long, because,
as I say, a GUID's size is 16 bytes,
and a long's size is 8 bytes. You
cannoy happily discard 8 bytes off a
GUID, even if they are zeroes! :-)

A Guid is merely a 128 bit data structure and a long is a 64 bit data structure...

That means that for as long as the upper 64 bits are Zeroes, we can safely discard them an at a later time reconstruct them as Zeroes are not meaning full data in this case. So yes it is loss of data, but under circumstances it is loss of data that can be reconstructed. (Think in terms of compression)

This is no different that when you say do:

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;

These explicit conversions are not built into the system as it is not so one must do it differently.

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);
}

Obviously this should never be used with GUID's in genneral, but is safe to use for as long as the GUID only has 64 bits of "actual data", best way to ensure that is to never use it on guids unless they where created using a long.

As a precaution I have added the throwing of an OverflowException in cases where the Guid actually stores anything but 0'es in the last 64 bits as the resulting long would not be able to be converted back to the same Guid.

So as such...

As long as the guid created fits in
the the long, it is possible? It's
just when it goes over the long's
specified size. Correct?

Is true... Obviously the corresponding long value of the GUID is not easy readable, here are some examples (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

And yes conversion of those works both ways and for any long value you can think off...

But because you state that:

The Guid creation is outside of my control.

It is extremely unlikely that you can actually do this, instead it is most likely that the Guid you have is generated with any of the common algorithms, and that will make the Guid unusable in this scenario.


Now does this make any sense to do?... That requires an insight to a specific situation, and is a whole other discussion...

余厌 2024-10-03 12:32:56

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

A GUID is 16 bytes long. A "long" is often understood as being 64 bits (i.e. 8 bytes) long. You cannot convert between those without losing or providing extra data.

空城旧梦 2024-10-03 12:32:56

我知道这个问题确实很老,但它是第一个谷歌结果,我想提供我正在讨论的答案。

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

我编写了一个 UInt128 类,具有高 UInt64 和低 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);
    }

也许它可以帮助某人!

I know this Question is really old, but its the First Google Result, and i wanted to provide the answer im going with.

Guid isnt a Int64 as the others already stated, instead its two UInt64's.

I Wrote a UInt128 Class, with a High, and a Low UInt64. From there you need to just convert between those:

    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);
    }

Maybe it helps someone!

秋意浓 2024-10-03 12:32:56

您可以使用 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)。如果您需要更多,则必须使用另一套。

每组都是无符号整数的十六进制表示,因此您可以尝试各种可能性。

You can using Guid constructor, a simple but not flawless example:

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);

The first set can handle up to 4294967295 (int). If you need more than it then you have to use another set.

Each set is a hex representation of a unsigned integer, so you can play around with the possibilities.

忆悲凉 2024-10-03 12:32:56
public static Guid ToGuid(long value)
{
    byte[] bytes = new byte[16];
    BitConverter.GetBytes(value).CopyTo(bytes, 0);
    return new Guid(bytes);
}

希望这个代码对你有帮助!

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

Hope, this code helps you!!!

我的鱼塘能养鲲 2024-10-03 12:32:56

只要您必须使用不超过 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

As long as you have to operate with positive integer values that not exceed Guid size, you can convert number to Guid like this:

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

and convert it back like:

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

In other cases it is better to use bytes-conversion as mentioned above. Examples can be checked here: https://dotnetfiddle.net/Zx7faI

浪漫之都 2024-10-03 12:32:56

您可以做的是将长整型(64 位)映射到 GUID(128 位)。
您不能将 GUID(128 位)映射到 long(64 位)。
您真正想要的是将 GUID 映射到 uint128(或 int128)。
当然,将 long 映射到 GUID 需要用零填充 uint128 的上部。

您需要考虑的是 GUID 按字节的特殊排序顺序(每个字节的优先级),以便您可以像使用 long (long = int64) 一样对 GUID 进行范围比较。

为此,你必须看看这个答案:
SQL Server GUID 排序算法

了解如何将 long 映射到ulong 和 int 到 uint,请参阅:
在 C# 中将 ulong 映射到 long?

了解如何将 UInt128 转换为 GUID,请参阅 ToGuidBytes() 和github 上 UInt128.cs 中的 ToGuid() 以及将 long 转换为 UInt128 的方法,请参阅 UInt128.cs 的构造函数。

public byte[] ToGuidBytes()
{
    // byte[] ba = this.ToByteArrayLowToHighEnsured();
    byte[] ba = this.ToByteArray(); // Fast 

    int[] guidByteOrder = new int[16] // 16 Bytes = 128 Bit 
       {10, 11, 12, 13, 14, 15,  8,  9,  6,  7,  4,  5,  0,  1,  2,  3};
    // {00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15}

    byte[] guidBytes = new byte[16];
    for (int i = 0; i < 16; ++i)
    {
        guidBytes[guidByteOrder[15 - i]] = ba[i];
    } // Next i 
    guidByteOrder = null;
    ba = null;

    return guidBytes;
} // End Function ToGuidBytes 


public System.Guid ToGuid()
{
    return new System.Guid(this.ToGuidBytes());
}

对于 System.Guid.NewGuid() 请参阅“NextUInt128< /a>":

以及一些测试来证明/检查它是否有效:
BigIntUidTests.cs

买者自负:
我不知道小端机与大端机将如何影响结果。

What you can do is map a long (64 bit) to a GUID (128 bit).
What you can't do is map a GUID (128 bit) to a long (64 bit).
What you actually want is mapping a GUID to a uint128 (or a int128).
Of course, mapping a long to a GUID requires a fillup of the upper part of uint128 with a zero.

What you need to consider is the special sort order of a GUID by its bytes (precendence of each byte), so that you can range-compare your GUIDs like you can with a long (long = int64).

For that you have to look at this answer:
SQL Server GUID sort algorithm

For how to map a long to a ulong, and a int to a uint, see:
Mapping a ulong to a long in C#?

For how to convert a UInt128 to a GUID, see ToGuidBytes() and ToGuid() in UInt128.cs on github and for converting a long into a UInt128, see the constructor of UInt128.cs.

public byte[] ToGuidBytes()
{
    // byte[] ba = this.ToByteArrayLowToHighEnsured();
    byte[] ba = this.ToByteArray(); // Fast 

    int[] guidByteOrder = new int[16] // 16 Bytes = 128 Bit 
       {10, 11, 12, 13, 14, 15,  8,  9,  6,  7,  4,  5,  0,  1,  2,  3};
    // {00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15}

    byte[] guidBytes = new byte[16];
    for (int i = 0; i < 16; ++i)
    {
        guidBytes[guidByteOrder[15 - i]] = ba[i];
    } // Next i 
    guidByteOrder = null;
    ba = null;

    return guidBytes;
} // End Function ToGuidBytes 


public System.Guid ToGuid()
{
    return new System.Guid(this.ToGuidBytes());
}

For System.Guid.NewGuid() see "NextUInt128":

And some tests to proof/check this works:
BigIntUidTests.cs

Caveat emptor:
I don't know how a little vs. big endian machine will influence the result.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文