我正在尝试创建一个天气结果列表(自定义POCO)的简单HashCode,并想知道我正在做什么是好/好。
我有一个基于时间的过程,可以检查5个地点的天气结果。我将每个天气结果存储在一个List中:
{
"results": [
{
"Id": 1,
"Location": "New York City",
"Temp": "21.7",
"Metric": "Celsius"
},
{
"Id": 2,
"Location": "San Francisco",
"Temp": "18.1",
"Metric": "Celsius"
},
....
{
"Id": 5,
"Location": "Melbourne",
"Temp": "33.1",
"Metric": "Celsius"
}
]
}
所以我希望得到一个HashCode /唯一指纹..将其存储在数据库中。稍后,我将再次获取最新的天气结果......这次将最近的结果与之前的结果(在数据库中)进行比较。
为此,我正在做以下事情:
private static string ToHash(IEnumerable<Weather> weatherResults)
{
byte[] hash;
// MD5 or SHA256?
using (var algorithm = MD5.Create())
{
var json = JsonConvert.SerializeObject(weatherResults);
hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(json));
}
return Encoding.UTF8.GetString(hash);
}
MD5
,因为我不关心安全性(例如,这不是我们存储的密码),并希望这很快。当我执行代码(上面)时,我得到一些奇怪的文本结果......这是一个快照:
所以代码似乎生成了我的列表的一些文本表示。我可以将此文本存储到数据库中。
所以感觉就像,我正在做的事情还可以 - >我希望有人确认我正在做的步骤是否正常。
当我执行代码(上面)时,我得到了一些奇怪的文本结果
那是因为你将任意二进制数据(加密哈希)视为UTF-8编码的文本数据。这就像试图在记事本中打开JPG文件 - 你会看到垃圾,因为JPG文件不是文本文件。
如果需要可打印文本,则应转换为十六进制或base64。 Base64可能是最简单的:
return Convert.ToBase64String(hash);
请注意,如果将return语句放在using
语句中,则甚至不需要额外的局部变量:
private static string ToHash(IEnumerable<Weather> weatherResults)
{
using (var algorithm = MD5.Create())
{
var json = JsonConvert.SerializeObject(weatherResults);
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(json));
return Convert.ToBase64String(hash);
}
}
这个人个人觉得有些脆弱 - 它依赖于POCO的精确JSON表示。特别是,如果您要更改序列化的某些方面,例如更改JSON中的字段名称,即使数据没有,哈希也会改变,这可能不是你想要的。再举一个例子,假设您在POCO中添加了一个int
字段 - 所有现有数据的JSON表示将更改为包含该值,即使它为0,因此所有哈希值都会发生变化。
(这也是散列数据的效率很低的方法,但这可能并不重要。)
这对您来说可能都很好,但随着数据类型的发展,您需要考虑您的要求。