AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller Suche
Thema durchsuchen
Ansicht
Themen-Optionen

Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller Suche

Ein Thema von juergen · begonnen am 4. Jul 2015 · letzter Beitrag vom 12. Jul 2015
Antwort Antwort
freimatz

Registriert seit: 20. Mai 2010
1.495 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S

  Alt 6. Jul 2015, 14:26
Ich bleibe nun bei meinen 2 Stringlisten.
„Wer als Werkzeug nur einen Hammer hat, sieht in jedem Problem einen Nagel.“
Wer als Werkzeug nur eine TStringlist kennt, für den sind alles Strings
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S

  Alt 6. Jul 2015, 15:51
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.
Angehängte Dateien
Dateityp: zip dp_185758_minimal.zip (902,6 KB, 15x aufgerufen)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von juergen
juergen

Registriert seit: 10. Jan 2005
Ort: Bönen
1.176 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S

  Alt 6. Jul 2015, 16:08
@SirRufo,
DAS sieht sehr interessant aus! (deinen letzten Post habe ich erst nach dem Abschicken gesehen...)
Vielen Dank für deine Geduld. Im Moment habe ich kein Zugriff auf Delphi. Bevor ich versuche das heute Abend zu verstehen eine wichtige Frage vorab: Besteht mit diesem Konzept auch die Möglichkeit die Daten zu speichern und beim Starten des Programms wieder zu laden? Und WIE genau fülle ich die TObjectList mit den Daten?

@freimatz,
ich gebe dir zum Teil Recht. Ich nutze Delphi hobbymäßig und habe schon einiges gelernt, aber bei weitem nicht die "komplzierteren Sachen". Das eigentliche Konzept wird wohl bleiben. Eine angepasste StringList für die reine Suche der Dateinamen mit "Referenzzeiger" auf die "Master"-StringList, Ich habe bis jetzt keine Alternativen erkannt (Schnelligkeit der Suche).
Wo du Recht hast ist natürlich die Datenhaltung in der "Master"-StringList. Da hat Sir Rufo gerade eine sehr interessante Alternative aufgezeigt. Wenn sich das ganze auch abspeichern und neu laden lässt wäre ich ja weg von der "einfachen" StringList.
Ich muss aber auch abwägen: Mit welchem für mich VERTRETBAREN Aufwand kann ich WAS umsetzen...


Edit Roter Kasten: Oh Mann, vielen Dank für deine Mühe. Ich werde mir das heute Abend anschauen und freu mich schon drauf.
Jürgen
Indes sie forschten, röntgten, filmten, funkten, entstand von selbst die köstlichste Erfindung: der Umweg als die kürzeste Verbindung zwischen zwei Punkten. (Erich Kästner)
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#4

AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S

  Alt 6. Jul 2015, 17:05
Besteht mit diesem Konzept auch die Möglichkeit die Daten zu speichern und beim Starten des Programms wieder zu laden? Und WIE genau fülle ich die TObjectList mit den Daten?
Eine Objektliste füllt man mit Daten, indem man ein Objekt erzeugt und der Objektliste hinzufügt (Add). Zurück erhält man den Index des neu hinzugefügten Objekts. Steht übrigens alles in der Online-Hilfe zu TObjectList ...
Da es sich beim Inhalt des Objekts um reinen Text handelt (auch Datumse kann man als String abspeichern), genügt z.B. eine CSV-Datei (Comma Separated Values), die man via Stringliste einliest und die einzelnen Strings via DelimitedText voneinander trennt. Eine solche Speichermethode könnte z.B. so aussehen:
Delphi-Quellcode:
Procedure FormMain.Speichern(Const Dateiname : String);
Const
  K = ';';
Var
  i,z : Integer;
  Liste : TStringList;
Begin
  Liste := TStringList.Create;

  Try
    z := MyObjectList.Count;
    If z > 0 Then
    For i := 0 To z-1 Do
      Liste.Append(MyObjectList.Dateiname + K + DateTimeToStr(MyObjectList.Datum));

    Liste.SaveToFile(Dateiname);
  Finally
    Liste.Free;
  End;
End;
Ähnlich würde dann das Einlesen erfolgen:
Delphi-Quellcode:
Procedure FormMain.Einlesen(Const Dateiname : String);
Const
  K = ';';
Var
  DList,
  Liste : TStringList;
  Id,
  i,z : Integer;
  Obj : TMyObjekt;

Begin
  Liste := TStringList.Create;
  DList := TStringList.Create;

  Try
    Anzahl := 0;
    DList.Delimiter := K;
    DList.StrictDelimiter := True;
    Liste.LoadFromFile(Dateiname);
    z := Liste.Count;
    If z > 0 Then
    For i := 0 To z-1 Do
    Begin
      DList.DelimitedText := Liste[i];
      If DList.Count = 2 Then
      Begin
        Obj := TMyObjekt.Create;
        Obj.Dateiname := DList[0];
        Obj.Datum := StrToDateTime(DList[1]);
        Id := MyObjectList.Add(Obj);
        If Id < 0 Then Obj.Free; // dann ist nämlich das Add mißlungen und das Objekt muß freigegeben werden
      End;
    End;
  Finally
    DList.Free;
    Liste.Free;
  End;
  ShowMessage('Es wurden ' + IntToStr(MyObjectList.Count) + 'Objekte eingelesen ...');
End;
Alles ohne Gewähr, da frei in den Editor getippt und daher ungetestet.
  Mit Zitat antworten Zitat
Benutzerbild von juergen
juergen

Registriert seit: 10. Jan 2005
Ort: Bönen
1.176 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S

  Alt 6. Jul 2015, 20:25
@Sir Rufo,
dein Projekt habe ich mir angesehen. Was soll ich sagen...außer Danke für etliche Denkanstöße. Aber ehrlich gesagt verstehe ich auch vieles nicht. Ich habe aber wieder einiges dazugelernt. Interessant ist aber auch die IOUtils-Unit mit den vielen Eigenschaften wie z.B. Predicate und das verwenden von mehreren Directories.

Ich werde nun erst mal klein anfangen und meine Master-StringList umstellen auf TObjectList! Mit den ganzen Beispielen bekomme ich das hin, denke ich.

@Perlsau,
auch dir danke ich für die Denkanstöße. TObjectList scheint mir nun immer sympatischer und vom Gefühl her denke ich dass es das richtige ist.
Jürgen
Indes sie forschten, röntgten, filmten, funkten, entstand von selbst die köstlichste Erfindung: der Umweg als die kürzeste Verbindung zwischen zwei Punkten. (Erich Kästner)
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#6

AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S

  Alt 6. Jul 2015, 21:17
@Perlsau,
auch dir danke ich für die Denkanstöße. TObjectList scheint mir nun immer sympatischer und vom Gefühl her denke ich dass es das richtige ist.
Dann hat sich der Aufwand also gelohnt: Man konnte dich von einem besseren Konzept überzeugen, denn das war ja auch dein eigentliches Anliegen

Die Welt ist schön
  Mit Zitat antworten Zitat
Bentissimo

Registriert seit: 25. Apr 2006
Ort: Friedenfels
82 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Konzeptfrage: Datenhaltung vieler Datei-Infos und deren Darstellg mit schneller S

  Alt 7. Jul 2015, 10:23
Wenn ohnehin schon das QuantumGrid im Einsatz ist, wäre der Einsatz der TdxMemData Komponente in Verbindung mit der Property Options.IncSearch für ausgewählte Spalten vielleicht eine Überlegung wert.

Das Speichern und Laden beherrscht diese Komponente bereits und die Suche wäre ebenfalls zumindest schon zum Teil abgedeckt.

Erfüllt die Anforderung vielleicht noch nicht zu 100%, aber dafür lässt sich ein Prototyp vermutlich in einer Stunde zusammen bauen.
Stephan Schmahl
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01: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