我试图根据Delphi 2010中的大小对文件列表进行排序。 我已经递归地获取了所有文件大小,文件创建日期和文件位置路径,但我在排序时遇到问题。
我的结果如下:
MB 57.682(60483584) - 08-06-2017 15:03 - o:\ Thumbs.db
MB 4.217(4422144) - 08-06-2017 13:48 - o:\ bmp \ Thumbs.db
数据必须按从最大文件到最小文件的顺序排序,并将结果存储到文件中。
我使用字符串格式化人类可读形式的文件大小。
在这种情况下,正确的方法是什么? 我应该将数据存储为csv值,然后尝试对它们进行排序吗? 我应该使用字符串列表吗?
这是我正在使用的代码:
procedure FasterSubFilesList_mmg(folder, exts: string; files: TStrings);
// builds recursive list of files matching set of extensions like '.exe .txt.htm'
function ext(filename: string): string;
begin result:= lowercase(extractFileExt(filename));
end;
CONST
SizeUnits : ARRAY[0..8] OF PChar = ('bytes','KB','MB','GB','TB','PB','EB','ZB','YB');
FUNCTION FormatByteSize(Size : UInt64 ; Decimals : BYTE) : String; OVERLOAD;
VAR
I : Cardinal;
S : Extended;
BEGIN
S:=Size;
FOR I:=LOW(SizeUnits) TO HIGH(SizeUnits) DO BEGIN
IF S<1024.0 THEN BEGIN
IF I=LOW(SizeUnits) THEN Decimals:=0;
Result:=Format('%.'+IntToStr(Decimals)+'f',[S]);
{adaug dimensiune urmata de unitatea de masura}
//Result:=Result+' '+StrPas(SizeUnits[I]);
{adaug unitatea de masura urmata de dimensiune}
Result:=StrPas(SizeUnits[I])+' '+Result;
EXIT
END;
S:=S/1024.0
END
END;
FUNCTION FormatByteSize(Size : UInt64) : String; OVERLOAD;
VAR
P : Integer;
BEGIN
Result:=FormatByteSize(Size,3);
IF Size>=1024 THEN BEGIN
P:=PRED(LastDelimiter(' ',Result));
WHILE COPY(Result,P,1)='0' DO BEGIN
DELETE(Result,P,1);
DEC(P)
END;
IF CharInSet(Result[P],['.',',']) THEN DELETE(Result,P,1)
END
END;
{ functie pentru a afla dimensiunea unui fisier }
function GetFileSize_mmg(const FileName: string): Int64;
var
fad: TWin32FileAttributeData;
begin
if not GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @fad) then RaiseLastOSError;
//GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @fad);
Int64Rec(Result).Lo := fad.nFileSizeLow;
Int64Rec(Result).Hi := fad.nFileSizeHigh;
end;
procedure AddFolder(dir: string);
var F: TSearchRec;
size:string;
data_creare_fisier:string;
const
//findTypes=faArchive+faHidden+faReadOnly+faAnyFile+faDirectory;
findTypes=faAnyFile;
begin
dir:= excludetrailingbackslash(dir)+'\';
if FindFirst(dir+'*.*', findTypes, F)=0 then
try
repeat
if (F.attr and faDirectory=faDirectory) then
begin
if (F.Name<>'.') and (F.Name<>'..') then AddFolder(dir+F.Name);
end
else
if (exts='*') or (pos(ext(F.Name)+' ', exts)>0) then
size:=FormatByteSize(GetFileSize_mmg(dir+F.name));
shortdateformat:='dd-mm-yyyy';
data_creare_fisier:=formatdatetime(shortdateformat+' hh:nn',filedatetodatetime(f.time));
files.Add(size+' ('+inttostr(GetFileSize_mmg(dir+F.name))+') - '+data_creare_fisier+' - '+dir+F.Name);
//files.Add('"'+size+'","'+inttostr(GetFileSize_mmg(dir+F.name))+'","'+data_creare_fisier+'","'+dir+F.Name+'"');
//files.Add(inttostr(GetFileSize_mmg(dir+F.name))+' ('+size+') - '+data_creare_fisier+' - '+dir+F.Name);
until FindNext(F)<>0;
finally FindClose(F) end;
end;
begin
if (trim(exts)='') or (exts='*') or (exts='*.*') then exts:='*'
else exts:= trim(lowercase(exts))+' ';
files.clear;
AddFolder(folder);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
FilesList: TStringList;
i:integer;
lista_descrescatoare:Tstrings;
begin
ListBox_fisiere_de_verificat.Items.Clear;
//listbox_fisiere_de_verificat.Items.BeginUpdate;
//afiseaza_in_listbox_fisiere_ce_pot_fi_procesate('O:\','*.*',true,10,listbox_fisiere_de_verificat,false,memo_loguri);
//listbox_fisiere_de_verificat.Items.EndUpdate;
memo_loguri.lines.add(FormatDatetime('dd-mm-yyyy hh:mm:ss', Now) +' - start listare fisiere');
FilesList:=Tstringlist.Create;
FilesList.Sorted:=true;
FilesList.Sort;
FasterSubFilesList_mmg('o:\','*.*',FilesList);
listbox_fisiere_de_verificat.items.AddStrings(FilesList);
memo_loguri.lines.add(' - total fisiere:'+inttostr(fileslist.count));
memo_loguri.lines.add(FormatDatetime('dd-mm-yyyy hh:mm:ss', Now) +' - stop listare fisiere');
end;
谢谢!
答案 0 :(得分:2)
考虑到您已经拥有FilesList TStringList中的文件列表,您可以在那里对它们进行排序。您可以调用CustomSort方法,提供自定义比较功能以指示哪个文件大于另一个文件。
function FileGreater(FileList: TStringList; Index1: integer; Index2: integer): integer;
var IniPos1, EndPos1, IniPos2, EndPos2: integer;
Size1, Size2: Int64;
begin
IniPos1 := Pos('(', FileList[Index1]) + 1;
EndPos1 := Pos(')', FileList[Index1]) - 1;
IniPos2 := Pos('(', FileList[Index2]) + 1;
EndPos2 := Pos(')', FileList[Index2]) - 1;
Size1 := StrToint64(Copy(FileList[Index1], IniPos1, EndPos1 - IniPos1));
Size2 := StrToint64(Copy(FileList[Index2], IniPos2, EndPos2 - IniPos2));
if Size1 = Size2 then Result := 0
else if Size1 < Size2 then Result := -1
else Result := 1;
end;
现在你打电话:
FileList.CustomSort(FileGreater);
PS:正如David Heffernan在评论中所说,StrToInt返回一个LongInt,因此它只适用于高达2Gb的文件。我已经更新了使用StrToInt64的答案,但您最好使用适当的结构来存储文件的数据而不是这个快速修复。