![]() |
AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Die Suche nach einer Datei (bzw. Filter) dauert dann ca. 2 Sekunden. Die Daten in der Datei werden in eine einfache Stringlist geladen, sind nicht sortiert, es müssen alle Einträge durchlaufen werden. Wenn man hier mit Multithreading arbeiten würde, könnte man die Suche zeitlich noch deutlich optimieren. Bei den 800.000 Dateien wird die Datendatei ca. 46 MB groß, eingelesen in der Arbeitsspeicher werden ca. 100 BM benötigt. In der Datei wird das Verzeichnis (aber nicht mehrfach) und der Dateiname, das Datum, die Größe und das Änderungsdatum erfasst. Das Suchergebnis kann ich noch mal durch einen 2. Filter eingrenzen (siehe anliegenden Screenshot) |
AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S
Zitat:
|
AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S
Mmh, reicht da auch ein externes Tool wie Everything, Hddb oder sowas, die die MFT indexieren?
MfG Dalai |
AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S
Wenn der TE nur nach Dateinamen suchen möchte, reichen die hier vorgestellten Verfahren.
Ansonsten würde ich ein Fulltext-System wie Lucene empfehlen oder irgend etwas anderes 'Fertiges', wie mein Vorredner schon anmerkte. Bitte macht nicht den Fehler, für ein Standardproblem etwas eigenes zu programmieren. Außer exorbitanten Kosten gewinnt man dabei gar nichts. Siehe auch: ![]() |
AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S
Moin zusammen,
Wir hatten mal einen Thread der sich mit der Geschwindikgeit von Listen beschäftigt hat und bei ID und Pfad-Listen fällt mir gleich Hashlist und DirectoryList ein. Schaut doch mal bei ![]() Grüße in die Runde |
AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S
Zitat:
|
AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S
Hallo zusammen,
ich habe nun eine -naja- Q&D-Lösung, die für mich reicht. Externe Tools bieten meines Wissens nur das durchsuchen der MFT bei lokalen Laufwerken an. Aber vor allem möchte ich mein Tool nach meinen Bedürfnissen. :) Ich bleibe nun bei meinen 2 Stringlisten. In der ersten TStringList werden Dateipfad+Name (und jetzt neu) das Datum gespeichert (getrennt durch 5 Doppelpunkte). Anzeigen tue ich in einer TListbox im virtullen Modus nur die Dateinamen. In einer für Textsuche angepassten weiteren StringList von alzheimer speichere ich nur die Dateinamen und im Objekt die eindeutige Nummer der "Hauptliste". Somit habe ich in meiner Suchvorschau immer den benötigten, direkten Verweis auf die Hauptliste:
Delphi-Quellcode:
Die Suche bleibt immer noch so schnell, dass ich meine "Live"-Suche anwenden kann (bei jeder neuen Eingabe eines neuen Buchstaben wird neu gesucht).
ExtractFileName(copy(sl_Master[Integer(SearchForm.Listbox1.Items.Objects[i])], 1,
pos(':::::', sl_Master[Integer(SearchForm.Listbox1.Items.Objects[i])])-1) MP3-und Exif-Tags lese ich erst aus, wenn die Datei in der Listbox angeklickt wird. Da ich die Hauptliste sortiere nach Name, Verzeichnis, Dateiendung und nach Datum, benötige ich diese Infos ja in der Hauptliste. Hinzukommen wird noch die Sortierung nach Bewertung (MP3). Aber das funktioniert ja nach dem jetzigen System, indem ich einfach 6 Doppelpunkte als weiteren Trenner für die Bewertungen verwende. :oops: Das Ganze ist für mich überschaubar, umsetzbar und nun auch erweiterbar. Ist sicherlich nicht elegant (da ich mit copy() mir immer die "Teile" aus der Hauptstringlist heraus fischen muss) und eine 2. Liste verwalten muss, aber erfüllt erstmal seinen Zweck. Danke für eure Ideen und Ratschläge! :dp: |
AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S
Wenn du eine ListView nimmst mit
Delphi-Quellcode:
, dann kannst du das mit einer
OwnerData := True
Delphi-Quellcode:
sehr einfach behandeln.
TObjectList<T>
Delphi-Quellcode:
type
TDataItem = class property Name : string; property Date : TDateTime; end; TMyForm = class( TForm ) ListView1 : TListView; procedure ListView1Data( Sender:TObject; Item : TListViewItem ); private FAllList : TObjectList<TDataItem>; FHitList : TList<TDataItem>; procedure SetHitList( AHitList : TList<TDataItem> ); end; procedure TMyForm.SetDataList( AHitList : TList<TDataItem> ); begin // Alte Liste löschen if FHitList <> FAllList then FreeAndNil( FHitList ); // Neue Liste setzen FHitList := AHitList; // Items.Count setzen if Assigned( FHitList ) then ListView1.Items.Count := FHitList.Count else ListView1.Items.Count := 0; end; procedure ListView1Data( Sender:TObject; Item : TListViewItem ); var LItem : TDataItem; begin LItem := FHitList[Item.Index]; Item.Caption := LItem.Name; Item.SubItems.Add( DateToStr( LItem.Date ) ); end; |
AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S
Zitat:
Wer als Werkzeug nur eine TStringlist kennt, für den sind alles Strings :twisted: |
AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S
Liste der Anhänge anzeigen (Anzahl: 1)
Hier mal so ein Minimal-Projekt im Anhang (Source + EXE) - ohne Threading, alles in einem Thread (der Start könnte etwas länger dauern)
Delphi-Quellcode:
unit Model_FileInfo;
interface uses System.Generics.Collections, System.SysUtils; type TObjectActionResult<TResult: class> = reference to procedure( AResult: TResult; AException: Exception; var ADispose: Boolean ); TFileInfo = class private FFullName: string; function GetFileName: string; function GetPath: string; public constructor Create( const AFileName: string ); property FullName: string read FFullName; property FileName: string read GetFileName; property Path: string read GetPath; end; TFileInfoList = class( TObjectList<TFileInfo> ) procedure Query( APredicate: TPredicate<TFileInfo>; callback: TObjectActionResult<TFileInfoList> ); end; implementation uses System.IOUtils; { TFileInfoList } procedure TFileInfoList.Query( APredicate: TPredicate<TFileInfo>; callback: TObjectActionResult<TFileInfoList> ); var LItem: TFileInfo; LResult: TFileInfoList; LDispose, LDummy: Boolean; begin LDispose := True; LResult := nil; try try LResult := TFileInfoList.Create( False ); for LItem in Self do begin if APredicate( LItem ) then LResult.Add( LItem ); end; except on E: Exception do begin callback( nil, E, LDummy ); Exit; end; end; callback( LResult, nil, LDispose ); finally if LDispose then LResult.Free; end; end; { TFileInfo } constructor TFileInfo.Create( const AFileName: string ); begin inherited Create; FFullName := AFileName; end; function TFileInfo.GetFileName: string; begin Result := TPath.GetFileName( FFullName ); end; function TFileInfo.GetPath: string; begin Result := TPath.GetFullPath( FFullName ); end; end.
Delphi-Quellcode:
unit Form_Main;
interface uses Model_FileInfo, System.Diagnostics, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.StdCtrls, Vcl.ExtCtrls; type TForm1 = class( TForm ) ListView1: TListView; Edit1: TEdit; StatusBar1: TStatusBar; QueryTimer: TTimer; procedure ListView1Data( Sender: TObject; Item: TListItem ); procedure Edit1Change( Sender: TObject ); procedure QueryTimerTimer( Sender: TObject ); private FQueryWatch: TStopwatch; FAllList: TFileInfoList; FHitList: TFileInfoList; procedure SetHitList( AHitList: TFileInfoList ); procedure BuildAllList( ); procedure QueryCallback( AResult: TFileInfoList; AException: Exception; var ADispose: Boolean ); procedure QueryData( const QueryStr: string ); public procedure AfterConstruction; override; procedure BeforeDestruction; override; end; var Form1: TForm1; implementation {$R *.dfm} uses System.IOUtils; { TForm1 } procedure TForm1.AfterConstruction; begin inherited; BuildAllList; QueryData( Edit1.Text ); end; procedure TForm1.BeforeDestruction; begin inherited; SetHitList( nil ); FreeAndNil( FAllList ); end; procedure TForm1.BuildAllList; var LPath, LFileName: string; begin FAllList := TFileInfoList.Create( True ); for LPath in TArray<string>.Create( {} TPath.GetPublicPath, {} TPath.GetLibraryPath, {} TPath.GetDocumentsPath, {} TPath.GetDownloadsPath, {} TPath.GetPicturesPath, {} TPath.GetMusicPath, {} TPath.GetMoviesPath ) do begin for LFileName in TDirectory.GetFiles( LPath, '*.*', TSearchOption.soAllDirectories ) do begin FAllList.Add( TFileInfo.Create( LFileName ) ); end; end; end; procedure TForm1.Edit1Change( Sender: TObject ); begin QueryTimer.Enabled := True; end; procedure TForm1.ListView1Data( Sender: TObject; Item: TListItem ); var LItem: TFileInfo; begin LItem := FHitList[ Item.Index ]; Item.Caption := LItem.FileName; Item.SubItems.Add( LItem.Path ); end; procedure TForm1.QueryCallback( AResult: TFileInfoList; AException: Exception; var ADispose: Boolean ); begin SetHitList( AResult ); ADispose := False; FQueryWatch.Stop; if Assigned( AException ) then StatusBar1.Panels[ 1 ].Text := AException.ToString( ) else StatusBar1.Panels[ 1 ].Text := string.Format( 'query finished in (%d ms)', [ FQueryWatch.ElapsedMilliseconds ] ); end; procedure TForm1.QueryData( const QueryStr: string ); var LQueryStrArr: TArray<string>; begin StatusBar1.Panels[ 1 ].Text := 'query data...'; FQueryWatch := TStopwatch.StartNew; if QueryStr.Trim( ) = '' then FAllList.Query( function( AFileInfo: TFileInfo ): Boolean begin Result := True; end, QueryCallback ) else begin LQueryStrArr := QueryStr.ToLower( ).Split( [ ' ' ] ); FAllList.Query( function( AFileInfo: TFileInfo ): Boolean var LQueryStr: string; begin for LQueryStr in LQueryStrArr do begin if not AFileInfo.FullName.ToLower.Contains( LQueryStr ) then Exit( False ); end; Result := True; end, QueryCallback ); end; end; procedure TForm1.QueryTimerTimer( Sender: TObject ); begin TTimer( Sender ).Enabled := False; QueryData( Edit1.Text ); end; procedure TForm1.SetHitList( AHitList: TFileInfoList ); begin if ( FHitList <> FAllList ) and ( FHitList <> AHitList ) then FreeAndNil( FHitList ); FHitList := AHitList; if Assigned( FHitList ) then begin ListView1.Items.Count := FHitList.Count; ListView1.Repaint; end else begin ListView1.Items.Count := 0; end; ListView1.Visible := Assigned( FHitList ); StatusBar1.Panels[ 0 ].Text := ListView1.Items.Count.ToString( ); end; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:31 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz