2017-06-13 22 views
0

Delphi 2010のサイズに基づいてファイルのリストをソートしようとしています。 すべてのファイルサイズ、ファイル作成日、ファイルの場所パスを再帰的に取得しましたが、ソートに問題がありますそれら。Delphi - サイズに基づいてファイルをソート

私の結果は次のようになります。

メガバイト57.682(60483584) - 2017年8月6日15:03 - O:\のThumbs.db

メガバイト4.217(4422144) - 2017年8月6日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

です。保存しておきたい場合は、SQLiteのような軽量データベースで保存してください。そうでない場合は、ビジュアルコントロールではなく、メモリコレクションでソートしてください。 – Victoria

+0

私はこの質問が本当にあなたの出力を格納しているかどうかに依存すると思うか、それはちょうど約視覚的なコントロールでソートですか? – Fero

+0

私は自分の質問を更新しました。私は、データをソートしてファイルに保存する必要があります。 – user2858981

答えて

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:デビッドHeffernanのコメントで言うように、それが唯一、最大2GBのファイルのために働くでしょうので、StrToIntは、倍長整数を返します。私はStrToInt64を使用するための答えを更新しましたが、この簡単な修正の代わりにファイルのデータを格納するために適切な構造を使用するほうがよいでしょう。

+2

TStringList.CustomSortについてはどうですか? –

+0

私はその方法を知らなかった。はい、それはさらに簡単です。 :-)私は答えを編集します。ありがとう。 –

+0

TStringList.CustomSortは確かに簡単で高速になります – Fero

関連する問題