本文整理自网络,侵删。
序言之前所说的获取文件MD5方法有性能问题,没多久我就遇到了,程序假死,卡顿。因此将获取文件MD5的方法改了一下,并测试了一下,大概性能提升了5倍,获取同一个文件的MD5,老方法用时是新方法的6倍。
改进原始获取文件MD5的方法:
// uses IdHashMessageDigestFunction StreamToMD5(s: TFileStream): string;var MD5Encode: TIdHashMessageDigest5;begin MD5Encode := TIdHashMessageDigest5.Create; try result := MD5Encode.HashStreamAsHex(s); finally MD5Encode.Free; end;end;Copy改进后的方法:
// uses System.HashFunction GetFileHashMD5(FileName: String): String;var HashMD5: THashMD5; BufLen, Readed: integer; Stream: TFileStream; Buffer: Pointer;
begin HashMD5 := THashMD5.Create; BufLen := 16 * 1024; Buffer := AllocMem(BufLen); try Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); try while Stream.Position < Stream.size do begin Readed := Stream.Read(Buffer^, BufLen); if Readed > 0 then begin HashMD5.update(Buffer^, Readed); end; end; finally Stream.Free; end; finally FreeMem(Buffer) end;
result := HashMD5.HashAsString.ToUpper;end;Copy测试结果文件大小原方法用时新方法用时1KB00:00:00.01300:00:00.00110KB00:00:00.02000:00:00.001100KB00:00:00.01000:00:00.0011MB00:00:00.06900:00:00.00810MB00:00:00.45500:00:00.091100MB00:00:04.33800:00:00.7711GB00:00:36.30600:00:07.4512GB00:01:13:21800:00:15:1013GB00:02:19:97700:00:23:1194GB00:02:25:50200:00:30:106以上测试结果肯定有偏差,因此将测试程序源码附上,以供需要的参考,程序界面:
unit Unit3;
interface
uses 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;
type 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 } end;
var Form2: TForm2; Function TransFloatToStr(Avalue: Double; ADigits: integer): String;
implementation
{$R *.dfm}
Function StreamToMD5(s: TFileStream): string;var MD5Encode: TIdHashMessageDigest5;begin MD5Encode := TIdHashMessageDigest5.Create; try result := MD5Encode.HashStreamAsHex(s); finally MD5Encode.Free; end;end;
Function GetFileHashMD5(FileName: String): String;var HashMD5: THashMD5; BufLen, Readed: integer; Stream: TFileStream; Buffer: Pointer;
begin HashMD5 := THashMD5.Create; BufLen := 16 * 1024; Buffer := AllocMem(BufLen); try Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); try while Stream.Position < Stream.size do begin Readed := Stream.Read(Buffer^, BufLen); if Readed > 0 then begin HashMD5.update(Buffer^, Readed); end; end; finally Stream.Free; end; finally FreeMem(Buffer) end;
result := HashMD5.HashAsString.ToUpper;end;
function TransBytesToSize(Bytes: integer): String;var temp: String;begin if Bytes < 1024 then { 字节 } begin result := IntToStr(Bytes) + ' Byte'; end
else if Bytes < 1024 * 1024 then { KB } begin temp := TransFloatToStr(Bytes / 1024, 2); result := temp + ' KB'; end
else if Bytes < 1024 * 1024 * 1024 then { MB } begin temp := TransFloatToStr(Bytes / (1024 * 1024), 2); result := temp + ' MB'; end
else { GB } begin temp := TransFloatToStr(Bytes / (1024 * 1024 * 1024), 2); result := temp + ' GB'; endend;
Function TransFloatToStr(Avalue: Double; ADigits: integer): String;var 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; end else result := FloatToStr(RoundTo(Avalue, -ADigits)); end else result := FloatToStr(RoundTo(Avalue, -ADigits));end;
procedure TForm2.Button1Click(Sender: TObject);var 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; end;
end;
procedure TForm2.Button2Click(Sender: TObject);var 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;
end;end;
end.
相关阅读 >>
Delphi d10.x 在android 9及更高版本下使用Delphi获取设备序列号?
Delphi getsys32path()得到系统system32路径
Delphi sysutils.strcopy、sysutils.strecopy
更多相关阅读请进入《Delphi》频道 >>