之前所说的获取文件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) 打赏
最新评论
没有收到邮件通知
我的评论通知貌似坏掉了,定位一下问题
测试一下重新部署后的邮件功能
居然看到自己公司的MIB库,诚惶诚恐
那可能是RobotFramework-ride的版本问题。我装的1.7.4.2,有这个限制。我有空再尝试下旧版本吧,感谢回复。
你好!我在python2.7中安装RobotFramework-ride的时候提示wxPython的版本最高是2.18.12,用pip下载的wxPython版本是4.10,而且我在那个路径下没有找到2
真的太好了,太感谢了,在bilibili和CSDN上都找遍了,终于在你这里找到了
看到下面的链接了,不用了。