计算字符串的校验和
本文关键字:校验和 字符串 计算 | 更新日期: 2023-09-27 18:28:42
我得到了一个任意长度的字符串(比如说5到2000个字符),我想为它计算校验和。
要求
- 每次对字符串进行计算时,都必须返回相同的校验和
- 校验和必须唯一(无冲突)
- 我无法存储以前的ID以检查冲突
我应该使用哪种算法?
更新:
- 是否有一种合理且独特的方法?即碰撞的可能性非常小
- 校验和应为字母数字
- 字符串是unicode
- 字符串实际上是应该翻译的文本,校验和与每次翻译一起存储(因此翻译后的文本可以与原始文本匹配)
- 校验和的长度对我来说并不重要(越短越好)
更新2
假设我得到了以下字符串"Welcome to this website. Navigate using the flashy but useless menu above"
。
该字符串在视图中的使用方式与linux中的gettext
类似。即用户只写(在剃刀视图中)
@T("Welcome to this website. Navigate using the flashy but useless menu above")
现在我需要一种识别该字符串的方法,这样我就可以从数据源获取它(数据源有几种实现)。必须使用整个字符串作为密钥似乎有点低效,因此我正在寻找一种从中生成密钥的方法。
这是不可能的。
如果不能存储以前的值,则无法创建小于字符串中信息的唯一校验和。
更新:
术语";"相当独特";没有意义,要么它是独一无二的,要么它不是。
为了获得相对较低的哈希冲突风险,可以使用相当大的哈希代码。
MD5算法例如产生一个16字节的散列码。使用某些保留所有字符的编码将字符串转换为字节数组,例如UTF-8,使用MD5
类计算哈希代码,然后使用BitConverter
类将哈希代码字节数组转换为字符串:
string theString = "asdf";
string hash;
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create()) {
hash = BitConverter.ToString(
md5.ComputeHash(Encoding.UTF8.GetBytes(theString))
).Replace("-", String.Empty);
}
Console.WriteLine(hash);
输出:
912EC803B2CE49E4A541068D495AB570
您可以为此使用加密哈希函数。其中大部分在.Net 中可用
例如:
var sha1 = System.Security.Cryptography.SHA1.Create();
byte[] buf = System.Text.Encoding.UTF8.GetBytes("test");
byte[] hash= sha1.ComputeHash(buf, 0, buf.Length);
//var hashstr = Convert.ToBase64String(hash);
var hashstr = System.BitConverter.ToString(hash).Replace("-", "");
注意:这是对原始问题的回答。
假设您希望校验和存储在固定大小的变量(即整数)中,则无法满足第二个约束。
校验和必须是唯一的(无冲突)
您无法避免冲突,因为不同的字符串将多于可能的校验和值。
我意识到这篇文章实际上很古老,但我偶然发现了它,并且在过去遇到过几乎相同的问题。我们需要查找一个nvarchar(8000)字段。
我们的解决方案是使用讨厌的查找字段的CHECKSUM创建一个持久化的计算列。我们有一个自动递增的ID字段,并键入(校验和,ID)
从表中读取时,我们编写了一个proc,它获取查找文本,计算校验和,然后获取校验和相等和文本相等的位置。
您可以根据上面的答案在应用程序级别轻松地执行校验和部分,并手动存储它们,而不是使用我们以DB为中心的解决方案。但关键是要获得一个大小合理的索引键,这样您的文本比较就可以针对一桶冲突而不是整个数据集进行。
祝你好运!
为了保证唯一性,对于几乎无限大的字符串,将可变长度字符串视为一组串联的子字符串,每个子字符串的长度为"x个字符"。您的哈希函数只需要确定最大子字符串长度的唯一性,然后生成一系列校验和数字来生成值。可以将其视为具有一组校验和数字的等效网络IP地址。
碰撞的问题是假设碰撞会强制使用较慢的搜索方法来解决每次碰撞。如果与哈希对象的数量相比,它们的可能冲突数量微不足道,那么作为一个整体,额外的开销将变为NIL。冲突是由于表的大小小于对象的最大数量。这种情况不一定是这样,因为表可能有"洞",并且表中的每个对象在碰撞时都可能有对象的引用计数。只有当此计数大于1时,才会发生冲突或同一子字符串的多个实例。