本文的项目环境为 .net 6.0 (.net 5.0 以上都支持)

在 .net 中获取字符串的 MD5 相信是非常容易的事情吧, 但是随便在网上搜一搜发现流传的版本还不少呢,比如:

  1. StringBuilder 版本(应该算是官方版本了,使用的人最多,我发现在 ABP 中也是使用的这个)

  2. BitConverter 版本

  3. StringConcat 版本 (字符串拼接,用的人很少,估计都知道性能不好)

但是它们是否是最佳实现? 我们来测试一下

StringBuilder 版本

public static string Md5_StringBuilder(string input)
{
using var md5 = MD5.Create();
var inputBytes = Encoding.UTF8.GetBytes(input);
var hashBytes = md5.ComputeHash(inputBytes);
var sb = new StringBuilder();
foreach (var hashByte in hashBytes)
{
sb.Append(hashByte.ToString("X2"));
}
return sb.ToString();
}

BitConverter 版本

public static string Md5_BitConverter(string input)
{
using var md5 = MD5.Create();
var inputBytes = Encoding.UTF8.GetBytes(input);
var hashBytes = md5.ComputeHash(inputBytes);
return BitConverter.ToString(hashBytes).Replace("-", "");
}

StringConcat 版本

public static string Md5_StringConcat(string input)
{
using var md5 = MD5.Create();
var inputBytes = Encoding.UTF8.GetBytes(input);
var hashBytes = md5.ComputeHash(inputBytes);
var output = string.Empty;
foreach (var hashByte in hashBytes)
{
output += hashByte.ToString("X2");
}
return output;
}

性能对比

先上我测试得到的数据(本机配置: 4 核 8 线程, 测试结果可能不一致)

看结果,的确是字符串拼接性能最差,但是 StringBuilder 好像也不是很高效啊,那个什么 Static 是啥玩意,怎么性能这么好,相对于 StringBuilder, 单线程性能提高了 3 倍, 多线性提高了 5 倍???

没错,这就是我要说的, 从 .net 5.0 开始提供了 2 个非常高效的方法

  • Convert.ToHexString
  • MD5.HashData

Convert.ToHexString 实例版本

public static string MD5_HexConvert_Instance(string input)
{
using var md5 = MD5.Create();
var inputBytes = Encoding.UTF8.GetBytes(input);
var hashBytes = md5.ComputeHash(inputBytes);
return Convert.ToHexString(hashBytes);
}

MD5.HashData 静态版本(强烈建议)

public static string MD5_HexConvert_Static(string input)
{
var inputBytes = Encoding.UTF8.GetBytes(input);
var hashBytes = MD5.HashData(inputBytes);
return Convert.ToHexString(hashBytes);
}

总结

  • 强烈建议 使用 MD5.HashData + Convert.ToHexString, 代码性能最高,也最简洁,只有 3 行

  • 一定不要 忘记释放 MD5,我看网上很多在使用实例版本 MD5.Create() 后都没有 Dispose, 这会导致 内存泄漏!!!

最后放上我的完整的测试代码

using System.Text;
using System.Security.Cryptography;
using System.Diagnostics; namespace ConsoleTest; class Program
{
public static string Md5_StringBuilder(string input)
{
using var md5 = MD5.Create();
var inputBytes = Encoding.UTF8.GetBytes(input);
var hashBytes = md5.ComputeHash(inputBytes);
var sb = new StringBuilder();
foreach (var hashByte in hashBytes)
{
sb.Append(hashByte.ToString("X2"));
}
return sb.ToString();
} public static string Md5_StringConcat(string input)
{
using var md5 = MD5.Create();
var inputBytes = Encoding.UTF8.GetBytes(input);
var hashBytes = md5.ComputeHash(inputBytes);
var output = string.Empty;
foreach (var hashByte in hashBytes)
{
output += hashByte.ToString("X2");
}
return output;
} public static string Md5_BitConverter(string input)
{
using var md5 = MD5.Create();
var inputBytes = Encoding.UTF8.GetBytes(input);
var hashBytes = md5.ComputeHash(inputBytes);
return BitConverter.ToString(hashBytes).Replace("-", "");
} public static string MD5_HexConvert_Instance(string input)
{
using var md5 = MD5.Create();
var inputBytes = Encoding.UTF8.GetBytes(input);
var hashBytes = md5.ComputeHash(inputBytes);
return Convert.ToHexString(hashBytes);
} public static string MD5_HexConvert_Static(string input)
{
var inputBytes = Encoding.UTF8.GetBytes(input);
var hashBytes = MD5.HashData(inputBytes);
return Convert.ToHexString(hashBytes);
} private const int LOOPCOUNT = 100_0000;
private static void CalcTime(Func<string, string> func, bool parallel = true)
{
Stopwatch stopwatch = Stopwatch.StartNew(); if (parallel)
{
Parallel.For(0, LOOPCOUNT, i =>
{
func("123456");
});
}
else
{
for (int i = 0; i < LOOPCOUNT; i++)
{
func("123456");
}
} stopwatch.Stop();
Console.WriteLine($"{func.Method.Name,32}: {stopwatch.ElapsedMilliseconds,4}ms");
} static void Main()
{
Test(); Console.ReadKey();
} private static void Test()
{
var functions = new List<Func<string, string>>
{
Md5_StringConcat,
Md5_StringBuilder,
Md5_BitConverter,
MD5_HexConvert_Instance,
MD5_HexConvert_Static,
}; foreach (var func in functions)
{
Console.WriteLine($"{func.Method.Name,32}: {func("123456")}");
} Console.WriteLine($"\n单线程 {LOOPCOUNT} 次用时统计:");
foreach (var func in functions)
{
CalcTime(func, false);
} Console.WriteLine($"\n多线程 {LOOPCOUNT} 次用时统计:");
foreach (var func in functions)
{
CalcTime(func, true);
}
}
}

.net core中你的MD5用对了吗?的更多相关文章

  1. 在 ASP.NET Core 中执行租户服务

    在 ASP.NET Core 中执行租户服务 不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: http://gunna ...

  2. ASP.NET Core 中的SEO优化(1):中间件实现服务端静态化缓存

    分享 最近在公司成功落地了一个用ASP.NET Core 开发前台的CMS项目,虽然对于表层的开发是兼容MVC5的,但是作为爱好者当然要用尽量多的ASP.NET Core新功能了. 背景 在项目开发的 ...

  3. Asp.Net Core中配置使用Kindeditor富文本编辑器实现图片上传和截图上传及文件管理和上传(开源代码.net core3.0)

    KindEditor使用JavaScript编写,可以无缝的于Java..NET.PHP.ASP等程序接合. KindEditor非常适合在CMS.商城.论坛.博客.Wiki.电子邮件等互联网应用上使 ...

  4. 在Asp.Net Core中配置使用MarkDown富文本编辑器实现图片上传和截图上传(开源代码.net core3.0)

    我们的富文本编辑器不能没有图片上传尤其是截图上传,下面我来教大家怎么实现MarkDown富文本编辑器截图上传和图片上传. 1.配置编辑器到html页 <div id="test-edi ...

  5. FormsAuthentication.HashPasswordForStoringInConfigFile方法再.net core中的替代代码

    FormsAuthentication.HashPasswordForStoringInConfigFile()这个加密方法再.net core中不存在了,可以用下面的方式达到一样的加密效果 usin ...

  6. .NET Core中的认证管理解析

    .NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...

  7. ASP.NET Core 中的那些认证中间件及一些重要知识点

    前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...

  8. Asp.net Core中使用Session

    前言 2017年就这么悄无声息的开始了,2017年对我来说又是特别重要的一年. 元旦放假在家写了个Asp.net Core验证码登录, 做demo的过程中遇到两个小问题,第一是在Asp.net Cor ...

  9. 在ASP.NET Core中使用百度在线编辑器UEditor

    在ASP.NET Core中使用百度在线编辑器UEditor 0x00 起因 最近需要一个在线编辑器,之前听人说过百度的UEditor不错,去官网下了一个.不过服务端只有ASP.NET版的,如果是为了 ...

  10. ASP.NET Core中的依赖注入(1):控制反转(IoC)

    ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...

随机推荐

  1. Kotlin 常用语法糖记录

    原文地址: Kotlin 常用语法糖记录 - Stars-One的杂货小窝 当使用 Kotlin 编程时,有一些常用的函数可以帮助我们简化代码并提高开发效率. 稍微列举下常用的方法 runCatchi ...

  2. AutoreleasePool 的总结

    1.创建和释放时机问题 App启动后,苹果在主线程 RunLoop 里注册了两个 Observer,其回调都是 _wrapRunLoopWithAutoreleasePoolHandler(). 第一 ...

  3. 【Python】数据可视化利器PyCharts在测试工作中的应用

    PyCharts 简介 PyCharts 是一个基于 Python 的数据可视化库,它支持多种图表类型,如折线图.柱状图.饼图等.PyCharts 提供了简洁的 API,使得用户能够轻松地创建各种图表 ...

  4. C标准库 操作文件

    C标准库 操作文件 数据持久化的两种方法:文件和数据库 文本文件和二进制文件 举个例子,写C++的代码,源代码为文本文件.编译出来的可执行文件(.exe)文件是二进制文件 文本文件 以文本的编码(AS ...

  5. RDB初步了解

    RDB概念 快照文件是.rdb结尾 redis6.2以前和之后(包括6.2)在什么条件下会保存rdb文件有所不同 以前 15min&&1个key(改变)调用保存 5min&&a ...

  6. typedef函数的使用

    typedef int INT; //相当于给int起了一个别名INT typedef struct Student { int sid; char name[100]; char sex; }ST; ...

  7. 烧死10亿脑细胞的SQL长啥样?

    1 前言 今天在生产中碰到了一个让我十分费解的 SQL,十分有趣. 2 现象 SQL 很好复现,就是逻辑看起来有点唬人 postgres=# create table test(id1 int,id2 ...

  8. 【go语言】2.1.3 函数的定义和使用

    在 Go 语言中,函数是一种代码抽象和复用的方式.函数可以接受参数,执行特定的操作,并返回结果. 函数的定义 函数的定义以 func 关键字开始,后面跟着函数名.参数列表.返回值列表(可选)以及函数体 ...

  9. 干了这么多年C#,后悔没早点用这种“分页”,简单/高效/易维护

    [前言] 干了这么多年C#,后悔没早点用这种"分页",简单/高效/易维护,比其它的分页方式强多了,不信你自己看. [正文] 支持.Net Core(2.0及以上)与.Net Fra ...

  10. 浅谈 Linux 下 vim 的使用

    Vim 是从 vi 发展出来的一个文本编辑器,其代码补全.编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用. Vi 是老式的字处理器,功能虽然已经很齐全了,但还有可以进步的地方.Vim 可 ...