我目前正在研究MongoDb作为一种可能的数据库选项,但我在处理Guid序列化时遇到了麻烦。起初我认为这可能是C#驱动程序序列化中的一个错误,但现在我认为这更可能是我的一个天真的假设。
为了帮助我将Bson base64表示来回转换为Guids,我编写了几个小powershell函数来提供帮助:
function base64toguid
{
param($str);
$b = [System.Convert]::FromBase64String($str);
$hex = "";
foreach ($x in $b) {
$hex += $x.ToString("x2");
}
$g = new-object -TypeName System.Guid -ArgumentList $hex;
return $g;
}
function guidtobase64
{
param($str);
$g = new-object -TypeName System.Guid -ArgumentList $str;
$b64 = [System.Convert]::ToBase64String($g.ToByteArray());
return $b64;
}下面是我遇到的问题的一个例子:
:) guidtobase64("53E32701-9863-DE11-BD66-0015178A5E3C");
ASfjU2OYEd69ZgAVF4pePA==
:) base64toguid("ASfjU2OYEd69ZgAVF4pePA==");
Guid
----
0127e353-6398-11de-bd66-0015178a5e3c在mongo shell中:
:) mongo
MongoDB shell version: 1.6.5
connecting to: test
> b = new BinData(3, "ASfjU2OYEd69ZgAVF4pePA==");
BinData(3,"ASfjU2OYEd69ZgAVF4pePA==")
> b.hex();
127e353639811debd66015178a5e3c
>如您所见,我得到的Guid与我输入的内容不匹配。我的函数和hex()返回相同的东西。如果将原始结果与结果进行比较:
53E32701-9863-DE11-BD66-0015178A5E3C
0127e353-6398-11de-bd66-0015178a5e3c
您可以看到,前3组十六进制对是颠倒的,但最后两组不是。这让我觉得Guid.ToString()有一些我不理解的地方。
有人能教教我吗?
发布于 2011-03-03 03:13:17
GUID中的字节顺序与它们在小端系统上的ToString()表示中的顺序不同。
您应该使用guid.ToByteArray()而不是ToString()。
而且,您应该使用new Guid(byte[] b)而不是$str来构造它。
要用纯C#来表达这一点:
public string GuidToBase64(Guid guid)
{
return System.Convert.ToBase64String(guid.ToByteArray()); // Very similar to what you have.
}
public Guid Base64Toguid(string base64)
{
var bytes = System.Convert.FromBase64String(base64);
return new Guid(bytes); // Not that I'm not building up a string to represent the GUID.
}请查看维基百科上的"Basic Structure" section of the GUID article以了解更多细节。
你会发现大部分数据都是以“本地”字节顺序存储的……这就是困惑的来源。
引述如下:
Data4存储字节的顺序与GUID文本编码中显示的顺序相同(请参见下文),但在小端系统(例如英特尔CPU)上,其他三个字段的顺序是相反的。
编辑:
Powershell版本:
function base64toguid
{
param($str);
$b = [System.Convert]::FromBase64String($str);
$g = new-object -TypeName System.Guid -ArgumentList (,$b);
return $g;
}作为额外的警告,您可以选择将字符串末尾的"==“去掉,因为它只是填充(如果您试图节省空间,这可能会有所帮助)。
发布于 2011-03-03 03:26:19
您需要调用接受字节数组的Guid构造函数。在Powershell中有特殊的语法需要这样做-如果你只是传递$b,它会告诉你找不到接受16个参数的构造函数,所以你必须将字节数组包装在另一个数组中:
$g = new-object -TypeName System.Guid -ArgumentList (,$b)发布于 2011-03-03 12:21:35
查看mongo网站上的c-sharp driver documentation,发现有一个为System.Guid提供的隐式转换。
所以在c#中(对不起,我的powershell有点生疏了),你可以这样写:
Guid g = Guid.NewGuid(); //or however your Guid is initialized
BsonValue b = g;我想反之亦然:
BsonValue b = // obtained this from somewhere
Guid g = b;如果您没有特别需要将Guid序列化为base64,那么直接将其转换为二进制文件的工作将会少得多(请注意,例如,将不会出现字节顺序问题)。此外,数据将以二进制形式存储在服务器上,因此它将比使用base64更节省空间。
https://stackoverflow.com/questions/5172134
复制相似问题