添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

之前所说的获取文件MD5方法有性能问题,没多久我就遇到了,程序假死,卡顿。因此将获取文件MD5的方法改了一下,并测试了一下,大概性能提升了5倍,获取同一个文件的MD5,老方法用时是新方法的6倍。

原始获取文件MD5的方法:

// uses IdHashMessageDigest
Function StreamToMD5(s: TFileStream): string;
  MD5Encode: TIdHashMessageDigest5;
begin
  MD5Encode := TIdHashMessageDigest5.Create;
    result := MD5Encode.HashStreamAsHex(s);
  finally
    MD5Encode.Free;

改进后的方法:

// uses System.Hash
Function GetFileHashMD5(FileName: String): String;
  HashMD5: THashMD5;
  BufLen, Readed: integer;
  Stream: TFileStream;
  Buffer: Pointer;
begin
  HashMD5 := THashMD5.Create;
  BufLen := 16 * 1024;
  Buffer := AllocMem(BufLen);
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
      while Stream.Position < Stream.size do
      begin
        Readed := Stream.Read(Buffer^, BufLen);
        if Readed > 0 then
        begin
          HashMD5.update(Buffer^, Readed);
    finally
      Stream.Free;
  finally
    FreeMem(Buffer)
  result := HashMD5.HashAsString.ToUpper;
原方法用时
新方法用时
00:00:00.013
00:00:00.001
00:00:00.020
00:00:00.001
100KB
00:00:00.010
00:00:00.001
00:00:00.069
00:00:00.008
00:00:00.455
00:00:00.091
100MB
00:00:04.338
00:00:00.771
00:00:36.306
00:00:07.451
00:01:13:218
00:00:15:101
00:02:19:977
00:00:23:119
00:02:25:502
00:00:30:106

以上测试结果肯定有偏差,因此将测试程序源码附上,以供需要的参考,程序界面:

unit Unit3;
interface
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Hash, IdHashMessageDigest,
  Vcl.StdCtrls, System.Math, IdGlobalProtocols;
  TForm2 = class(TForm)
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  Form2: TForm2;
  Function TransFloatToStr(Avalue: Double; ADigits: integer): String;
implementation
{$R *.dfm}
Function StreamToMD5(s: TFileStream): string;
  MD5Encode: TIdHashMessageDigest5;
begin
  MD5Encode := TIdHashMessageDigest5.Create;
    result := MD5Encode.HashStreamAsHex(s);
  finally
    MD5Encode.Free;
Function GetFileHashMD5(FileName: String): String;
  HashMD5: THashMD5;
  BufLen, Readed: integer;
  Stream: TFileStream;
  Buffer: Pointer;
begin
  HashMD5 := THashMD5.Create;
  BufLen := 16 * 1024;
  Buffer := AllocMem(BufLen);
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
      while Stream.Position < Stream.size do
      begin
        Readed := Stream.Read(Buffer^, BufLen);
        if Readed > 0 then
        begin
          HashMD5.update(Buffer^, Readed);
    finally
      Stream.Free;
  finally
    FreeMem(Buffer)
  result := HashMD5.HashAsString.ToUpper;
function TransBytesToSize(Bytes: integer): String;
  temp: String;
begin
  if Bytes < 1024 then { 字节 }
  begin
    result := IntToStr(Bytes) + ' Byte';
  else if Bytes < 1024 * 1024 then { KB }
  begin
    temp := TransFloatToStr(Bytes / 1024, 2);
    result := temp + ' KB';
  else if Bytes < 1024 * 1024 * 1024 then { MB }
  begin
    temp := TransFloatToStr(Bytes / (1024 * 1024), 2);
    result := temp + ' MB';
  else { GB }
  begin
    temp := TransFloatToStr(Bytes / (1024 * 1024 * 1024), 2);
    result := temp + ' GB';
Function TransFloatToStr(Avalue: Double; ADigits: integer): String;
  v: Double;
  p: integer;
  e: String;
begin
  if abs(Avalue) < 1 then
  begin
    result := FloatToStr(Avalue);
    p := Pos('E', result);
    if p > 0 then
    begin
      e := copy(result, p, length(result));
      setlength(result, p - 1);
      v := RoundTo(StrToFloat(result), -ADigits);
      result := FloatToStr(v) + e;
      result := FloatToStr(RoundTo(Avalue, -ADigits));
    result := FloatToStr(RoundTo(Avalue, -ADigits));
procedure TForm2.Button1Click(Sender: TObject);
  path: string;
  FileName: string;
  MD5: string;
  bytes: Integer;
  size: string;
  d1 : TDateTime;
begin
  if OpenDialog1.Execute then
  begin
    FileName := ExtractFileName(OpenDialog1.FileName);
    path := OpenDialog1.FileName;
    d1 := Now();
    MD5 := StreamToMD5(TFileStream.Create(path, fmOpenRead or fmShareDenyWrite));
    Label4.Caption := FormatDateTime('hh:nn:ss.zzz', (Now-d1));
    bytes := FileSizeByName(path);
    size := TransBytesToSize(bytes);
    Label2.Caption := MD5;
    Label3.Caption := size;
procedure TForm2.Button2Click(Sender: TObject);
  path: string;
  FileName: string;
  MD5: string;
  bytes: Integer;
  size: string;
  d2: TDateTime;
begin
  if OpenDialog1.Execute then
  begin
    FileName := ExtractFileName(OpenDialog1.FileName);
    path := OpenDialog1.FileName;
    d2 := Now();
    MD5 := GetFileHashMD5(path);
    Label8.Caption := FormatDateTime('hh:nn:ss.zzz', (Now-d2));
    bytes := FileSizeByName(path);
    size := TransBytesToSize(bytes);
    Label6.Caption := MD5;
    Label7.Caption := size;

这个方法应该还有进一步改进的可能,但现在时间太晚,后面找时间在尝试提升性能。

如有错误,敬请指出,感谢指正!     — 2020-07-26 00:31:09

赞(0) 打赏
转载请注明:飘零博客 » Delphi-改进获取文件MD5 Hash方法

相关推荐

评论 抢沙发

分类目录

站点统计

  • 日志总数:195
  • 评论总数:80
  • 页面总数:13
  • 最后更新:2024-04-27