[英]How can I generate a GUID for a string?
我在為字符串生成GUID時遇到問題 - 例如:
Guid g = New Guid("Mehar");
如何計算"Mehar"
的GUID? 我得到一個例外。
相當古老的這個線程,但這就是我們解決這個問題的方法:
由於來自.NET框架的Guid是任意16字節或128位,您可以通過將任何散列函數應用於生成16字節散列的字符串並隨后將結果傳遞給Guid構造函數來從任意字符串計算Guid。
我們決定使用MD5哈希函數,示例代碼可能如下所示:
string input = "asdfasdf";
using (MD5 md5 = MD5.Create())
{
byte[] hash = md5.ComputeHash(Encoding.Default.GetBytes(input));
Guid result = new Guid(hash);
}
請注意,這個Guid一代本身有一些缺陷,因為它取決於哈希函數的質量! 如果您的哈希函數為您使用的大量字符串生成相等的哈希值,則會影響您的軟件行為。
以下是產生128位摘要的最流行的哈希函數列表:
請注意,也可以使用其他散列函數來生成更大的摘要,並簡單地截斷它們。 因此,使用更新的散列函數可能是明智的。 列出一些:
今天(2013年8月)160bit SHA1哈希可以被認為是一個不錯的選擇。
您正在尋找的可能是生成版本3或版本5 UUID,它們是基於名稱的UUID。 (建議使用版本5)。 我認為.NET框架並不支持它。 請參見http://en.wikipedia.org/wiki/Universally_Unique_Identifier
我做了一些谷歌搜索,看看我是否能在Win32 API中找到一些東西,但沒有任何結果。 但是,我確信.NET框架在某處隱藏了一些實現,因為據我所知,在.NET中生成COM對象時,如果沒有提供顯式GUID,那么.NET框架會生成一個名稱基於UUID創建一個定義良好的ClassID和InterfaceID,即每次重新編譯時都不會改變的UUID(如VB6)。 但這可能是隱藏的,所以我猜你需要自己實現算法。 幸運的是,.NET提供了MD5和SHA1算法,所以我認為實現版本3和版本5 UUID應該太難了。
通常,很少有方法可以制作通用唯一ID(UUID RFC 4122 ,又名GUID)。 我們可以從Python借用這四個,並在C#中使用類似的東西:
uuid.uuid1([node[, clock_seq]])
從主機ID,序列號和當前時間生成UUID。 如果未給出node,則使用getnode()來獲取硬件地址。 如果給出clock_seq,則將其用作序列號; 否則,選擇隨機的14位序列號。
uuid.uuid3(namespace, name)
基於命名空間標識符(UUID)和名稱(字符串)的MD5哈希生成UUID。
uuid.uuid4()
生成隨機UUID。
uuid.uuid5(namespace, name)
基於命名空間標識符(UUID)和名稱(字符串)的SHA-1哈希生成UUID。
因此,如果您需要字符串的ID作為對象,而不是值的ID,您應該使用給定的字符串來uuid1
您的私有UUID。您的私有UUID使用uuid1
生成一次,然后將其用作uuid3
或uuid5
命名空間。
這些變體和版本在Wikipedia Universally_unique_identifier#Variants_and_versions中描述
你不能這樣使用GUID。 Guid的構造函數需要Guid的有效字符串表示。
您正在尋找的是一個哈希函數。 (例如: MD5 )
我認為你對Guid究竟是什么有誤解。 沒有像“Mehar”這樣的字符串的Guid表示。
有一個new Guid(String s)
重載的原因是你可以從一個典型的字符串表示創建一個guid,例如“00000000-0000-0000-0000-000000000000”。
有關Guid實際是什么的更多信息,請參閱wiki文章。
如果op的意圖是從某種類型的字符串哈希(MD5,SHA-1,et.c。)創建一個UUID(Guid),我發現這個非常相似的問題有這個很好的答案:
https://stackoverflow.com/a/5657517/430885
它有一個基於RFC4122§4.3的github-snippet的鏈接,它將從字符串和命名空間創建一個Guid(您可以自己選擇它來保證不受來自外部環境的沖突)。
直接鏈接到代碼段: https : //github.com/LogosBible/Logos.Utility/blob/master/src/Logos.Utility/GuidUtility.cs
這是我自己的方法,如果可能的話,我有意使用String進行十六進制轉儲 - 在視覺上可以看到至少有多大的字符串,如果需要的話 - 使用一些在線十六進制轉換器進行解碼。 但是如果字符串太長(超過16個字節) - 那么使用sha-1來計算哈希並從中生成guid。
/// <summary>
/// Generates Guid based on String. Key assumption for this algorithm is that name is unique (across where it it's being used)
/// and if name byte length is less than 16 - it will be fetched directly into guid, if over 16 bytes - then we compute sha-1
/// hash from string and then pass it to guid.
/// </summary>
/// <param name="name">Unique name which is unique across where this guid will be used.</param>
/// <returns>For example "{706C7567-696E-7300-0000-000000000000}" for "plugins"</returns>
static public String GenerateGuid(String name)
{
byte[] buf = Encoding.UTF8.GetBytes(name);
byte[] guid = new byte[16];
if (buf.Length < 16)
{
Array.Copy(buf, guid, buf.Length);
}
else
{
using (SHA1 sha1 = SHA1.Create())
{
byte[] hash = sha1.ComputeHash(buf);
// Hash is 20 bytes, but we need 16. We loose some of "uniqueness", but I doubt it will be fatal
Array.Copy(hash, guid, 16);
}
}
// Don't use Guid constructor, it tends to swap bytes. We want to preserve original string as hex dump.
String guidS = "{" + String.Format("{0:X2}{1:X2}{2:X2}{3:X2}-{4:X2}{5:X2}-{6:X2}{7:X2}-{8:X2}{9:X2}-{10:X2}{11:X2}{12:X2}{13:X2}{14:X2}{15:X2}",
guid[0], guid[1], guid[2], guid[3], guid[4], guid[5], guid[6], guid[7], guid[8], guid[9], guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]) + "}";
return guidS;
}
Guids是隨機的,它們本身並不分配給任何字符串或其他值。
如果需要這樣的鏈接,請將guid存儲在Dictionary中,並在創建新guid之前先檢查現有的guid。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.