代码之家  ›  专栏  ›  技术社区  ›  Punit Vora

如何创建确定性guid

  •  89
  • Punit Vora  · 技术社区  · 14 年前

    在我们的应用程序中,我们使用一个具有Guid值的属性创建Xml文件。此值需要在文件升级之间保持一致。因此,即使文件中的其他所有内容都发生了更改,属性的guid值也应该保持不变。

    一个明显的解决方案是创建一个带有文件名和guid的静态字典。然后,无论何时生成文件,我们都会在字典中查找文件名并使用相应的guid。但这是不可行的,因为我们可能会扩展到100个文件,并且不想维护大量的guid。

    因此,另一种方法是根据文件的路径使Guid相同。由于文件路径和应用程序目录结构是唯一的,因此该路径的Guid应该是唯一的。因此,每次运行升级时,文件都会根据其路径获得相同的guid。我找到了一个很酷的方法 Deterministic Guids

    private Guid GetDeterministicGuid(string input) 
    
    { 
    
    //use MD5 hash to get a 16-byte hash of the string: 
    
    MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider(); 
    
    byte[] inputBytes = Encoding.Default.GetBytes(input); 
    
    byte[] hashBytes = provider.ComputeHash(inputBytes); 
    
    //generate a guid from the hash: 
    
    Guid hashGuid = new Guid(hashBytes); 
    
    return hashGuid; 
    
    } 
    

    因此给定一个字符串,Guid将始终相同。

    5 回复  |  直到 14 年前
        1
  •  161
  •   Bradley Grainger    6 年前

    正如@bacar所说, RFC 4122 §4.3定义了创建基于名称的UUID的方法。这样做的好处(相对于只使用MD5散列)是保证这些uuid不会与非命名的uuid发生冲突,并且与其他基于名称的uuid发生冲突的可能性非常(非常)小。

    在.NET框架中没有本机支持来创建这些,但是我发布了 code on GitHub

    Guid guid = GuidUtility.Create(GuidUtility.UrlNamespace, filePath);
    

    为了进一步降低与其他GUID冲突的风险,可以创建一个私有GUID用作名称空间ID(而不是使用RFC中定义的URL名称空间ID)。

        2
  •  31
  •   Ben Gripka Javed Akram    12 年前

    这将把任何字符串转换成Guid,而不必导入外部程序集。

    public static Guid ToGuid(string src)
    {
        byte[] stringbytes = Encoding.UTF8.GetBytes(src);
        byte[] hashedBytes = new System.Security.Cryptography
            .SHA1CryptoServiceProvider()
            .ComputeHash(stringbytes);
        Array.Resize(ref hashedBytes, 16);
        return new Guid(hashedBytes);
    }
    

    有更好的方法来生成唯一的Guid,但这是一种将字符串数据键一致升级为Guid数据键的方法。

        3
  •  21
  •   bacar    14 年前

    正如Rob提到的,您的方法不会生成UUID,而是生成一个看起来像UUID的散列。

    RFC 4122 在UUID上特别允许确定性(基于名称的)UUID—版本3和版本5分别使用md5和SHA1。大多数人可能都熟悉版本4,它是随机的。 Wikipedia 提供了一个很好的版本概述(请注意,这里使用的“version”一词似乎描述了UUID的一种“类型”——版本5并不取代版本4)。

    似乎有一些库用于生成版本3/5uuid,包括 python uuid module , boost.uuid (C++)和 OSSP UUID

        4
  •  3
  •   Rob Fonseca-Ensor    14 年前

    您需要区分类的实例 Guid provider.ComputeHash ). 哈希比通过创建的Guid有更高的冲突几率(两个不同的字符串产生相同的哈希) Guid.NewGuid

    因此,您的方法的问题是,您必须确定两个不同的路径将产生相同的GUID的可能性。如果您需要一个对于任何给定的路径字符串都是唯一的标识符,那么最简单的方法就是 用绳子就行了 加密它 -你可以用ROT13或者更强大的东西。。。

        5
  •  1
  •   ryber    14 年前

    MD5很弱,我相信你可以用SHA-1做同样的事情,得到更好的结果。

    顺便说一句,仅仅是个人观点,把md5散列装扮成GUID并不能使它成为一个好的GUID。guid本质上是不确定的。这感觉像是作弊。为什么不直截了当地说它是输入的字符串散列呢。您可以使用此行而不是新的guid行:

    string stringHash = BitConverter.ToString(hashBytes)