Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Problem mit FindFirst und Dateiendungen (https://www.delphipraxis.net/82862-problem-mit-findfirst-und-dateiendungen.html)

Helmi 20. Dez 2006 21:17


Problem mit FindFirst und Dateiendungen
 
Hallo,

ich verwende folgende Procedure um die Dateinamen mit einer bestimmten Endung in einer Liste auflisten zu lassen:

Delphi-Quellcode:
procedure GetFilesInDirectory(Directory: String; const Mask: String; List: TStrings);
var
  SR: TSearchRec;

begin
  List.BeginUpdate;

    try
      List.Clear;

      If Directory <> '' then
        begin
          IncludeTrailingPathDelimiter(Directory);

          If FindFirst(Directory + Mask, faAnyFile - faDirectory, SR) = 0 then
            try
              repeat
                List.Add(Directory + SR.Name)
              until FindNext(SR) <> 0;
            finally
              FindClose(SR);
            end;
        end;
    finally
      List.EndUpdate;
    end;
end;
Das geht auch gut - zu gut sogar!

Aufgerufen wird die Procedure bei mir so:
Delphi-Quellcode:
GetFilesInDirectory(Masken_Ordner, '*.msk', Masken_Dateiliste);
In dem Ordner "Masken_Ordner" befinden sich eben Dateien mit der Endung "*.msk*". Diese werden auch in die Liste "Masken_Dateiliste" geschrieben.
Wenn aber nun eine Datei die Endung "*.msk2" hat z. B. wird sie trotzdem gefunden.

Wie kann ich verhindern, dass auch andere Dateien mit aufgelistet werden, sondern nur die mit der Endung *.msk?

litsa 20. Dez 2006 21:37

Re: Problem mit FindFirst und Dateiendungen
 
Wie wär's hiermit:
Delphi-Quellcode:
...
if UpperCase(ExtractFileExt(SR.Name))= '.MSK' then
  List.Add(Directory + SR.Name);
...

Christian Seehase 20. Dez 2006 21:52

Re: Problem mit FindFirst und Dateiendungen
 
Moin Helmi,

als Ergängzung zu Evangelias Beitrag:

Merk' Dir am Besten die übergebenen Maske.

Delphi-Quellcode:
var
  sMsk : string;

begin
  sMsk := UpperCase(ExtractFileExt(Mask));
  //...
end;
Dann musst Du das nur einmal machen.

Aber eines noch:

Das
Delphi-Quellcode:
faAnyfile - faDirectory
geht ja nun garnicht ;-)
(auch wenn es in diesem Falle funktioniert).

Es handelt sich hier um Bitwerte.
Wenn Du nun also einen rausrechnen willst dann mit and not

Delphi-Quellcode:
faAnyFile and not faDirectory

Helmi 20. Dez 2006 21:52

Re: Problem mit FindFirst und Dateiendungen
 
Zitat:

Zitat von litsa
Wie wär's hiermit:
Delphi-Quellcode:
...
if UpperCase(ExtractFileExt(SR.Name))= '.MSK' then
  List.Add(Directory + SR.Name);
...

Danke - so würds funktionieren, aber so richtig zufrieden bin ich nicht damit.

Denn für was gib ich denn dann bei FindFirst die Endung an?
Delphi-Quellcode:
FindFirst(Directory + Mask, faAnyFile - faDirectory, SR) = 0

Hawkeye219 20. Dez 2006 22:58

Re: Problem mit FindFirst und Dateiendungen
 
Hallo Helmi,

der Grund für das Verhalten von FindFirst/FindNext ist die Unterstützung der "alten" Dateinamen im 8.3-Format. Windows speichert zu jedem langen Dateinamen auch den passenden kurzen Dateinamen und überprüft diesen bei einer Suche ebenfalls. Der Namensanteil wird dabei mit einer Tilde (~) und einer fortlaufenden Nummer versehen, die Erweiterung nach 3 Zeichen abgeschnitten.

Die einzige Abhilfe hat dir litsa bereits genannt: eine zusätzliche Überprüfung der gefundenen Dateien. Wenn du dann noch das Funktionsergebnis beim Aufruf von IncludeTrailingPathDelimiter verwertest und Christians Hinweis berücksichtigst, dann sollte es funktionieren:

Delphi-Quellcode:
procedure GetFilesInDirectory(Directory: String; const Mask: String; List: TStrings);
var
  ext : string; // neu
  SR: TSearchRec;
begin
  List.BeginUpdate;
  try
    List.Clear;
    If Directory <> '' then
      begin
        ext := ExtractFileExt(Mask); // neu
        Directory := IncludeTrailingPathDelimiter(Directory); // Funktionsergebnis nicht verwerfen!
        If FindFirst(Directory + Mask, faAnyFile and (not faDirectory), SR) = 0 then // Hinweis von Christian
          try
            repeat
              if SameText(ExtractFileExt(SR.Name), ext) then // neu
                List.Add(Directory + SR.Name)
            until FindNext(SR) <> 0;
          finally
            FindClose(SR);
          end;
      end;
  finally
    List.EndUpdate;
  end;
end;
Gruß Hawkeye

bluescreen25 21. Dez 2006 08:14

Re: Problem mit FindFirst und Dateiendungen
 
mir ist so etwas aufgefallen, wenn die Mask mehr als 3 Zeichen hat also wie bei deinem Beispiel .msk2 (4 Zeichen)

Bei .ms1 .ms2 .ms3 klappt das bei mir.

Gruß, bluescreen25

Helmi 21. Dez 2006 08:34

Re: Problem mit FindFirst und Dateiendungen
 
Hallo,

danke für die Tips!

Ich hab mir jetzt aber fongendes überlegt:
Wenn ich sowieso ein zweites mal prüfen muss ob die Endung pass, dann kann ich ja bei FindFirst alle Dateien suchen lassen (*.*):

Delphi-Quellcode:
procedure GetFilesInDirectory(Directory: String; const Ext: String; List: TStrings);
var
  SR: TSearchRec;

begin
  List.BeginUpdate;

  try
    List.Clear;

    If Directory <> '' then
      begin
        Directory := IncludeTrailingPathDelimiter(Directory);
        If FindFirst(Directory + '*.*', faAnyFile and (not faDirectory), SR) = 0 then //hier
          try
            repeat
              If UpperCase(ExtractFileExt(SR.Name))= UpperCase(Ext) then
                List.Add(Directory + SR.Name);
            until FindNext(SR) <> 0;
          finally
            FindClose(SR);
          end;
      end;
  finally
    List.EndUpdate;
  end;
end;
So brauch ich mir die Endung nicht speichern.
einzigste Änderung im normalen Code: anstatt "*.msk*, muss ich jetzt ".msk" schreiben

Christian Seehase 21. Dez 2006 09:22

Re: Problem mit FindFirst und Dateiendungen
 
Moin Helmi,

Zitat:

Zitat von Helmi
So brauch ich mir die Endung nicht speichern.

stimmt, aber so musst Du bei jeder Datei zweimal UpperCase aufrufen, auch wenn das bei den Datenmengen um die es hier geht keinen spürbaren Einfluss auf die Performance haben wird.

Wenn übrigens so

Delphi-Quellcode:
pos(UpperCase(ExtractFileExt(sr.Name)),ext) > 0
kann die Maske auch mehrere Endungen enthalten (z.B. '.txt.lst'), wenn dann auch nicht mit Wildcards

Hawkeye219 21. Dez 2006 10:22

Re: Problem mit FindFirst und Dateiendungen
 
Hallo Helmi,

Zitat:

Zitat von Helmi
Wenn ich sowieso ein zweites mal prüfen muss ob die Endung pass, dann kann ich ja bei FindFirst alle Dateien suchen lassen (*.*)

Warum läßt du dir alle Dateien im Verzeichnis liefern, wenn dich nur eine Teilmenge interessiert? Damit schickst du ja auch alle Dateienamen durch UpperCase und einen Stringvergleich.

Zitat:

So brauch ich mir die Endung nicht speichern.
einzigste Änderung im normalen Code: anstatt "*.msk*, muss ich jetzt ".msk" schreiben
Dadurch wird die Routine aber auch unflexibler, weil sie Masken wie 'Level*.msk' nicht mehr unterstützt. Und das nur, weil du eine (lokale) Variable sparen möchtest?

Ich habe noch etwas festgestellt: bei der Verwendung von Jokerzeichen ('?' bzw. '*') in der Maske für die Namenserweiterung darf kein Vergleich der Extensions stattfinden, weil dieser Vergleich immer fehlschlagen würde. Die notwendigen Änderungen habe ich im folgenden Quelltext markiert:

Delphi-Quellcode:
procedure GetFilesInDirectory(Directory: String; const Mask: String; List: TStrings);
var
  ext : string;
  wild : Boolean; // neu
  SR: TSearchRec;
begin
  List.BeginUpdate;
  try
    List.Clear;
    If Directory <> '' then
      begin
        ext := ExtractFileExt(Mask);
        wild := (Pos('?', ext) > 0) or (Pos('*', ext) > 0); // neu
        Directory := IncludeTrailingPathDelimiter(Directory);
        If FindFirst(Directory + Mask, faAnyFile and (not faDirectory), SR) = 0 then
          try
            repeat
              if wild or SameText(ExtractFileExt(SR.Name), ext) then // geändert
                List.Add(Directory + SR.Name)
            until FindNext(SR) <> 0;
          finally
            FindClose(SR);
          end;
      end;
  finally
    List.EndUpdate;
  end;
end;
Ein Mangel läßt sich auf diesem Weg nicht so einfach umgehen: eine Maske wie '*.m??' liefert dir auch Dateinamen, deren Extension nicht genau drei Zeichen enthält.

Auch wenn du nicht alle Features der Routine im aktuellen Projekt brauchst, solltest du sie nicht entfernen - sie stören ja nicht. Irgendwann benötigst du sie vielleicht, und dann kannst du diese Funktion ohne Änderung wiederverwenden.

Gruß Hawkeye

ralfiii 26. Sep 2008 15:19

Re: Problem mit FindFirst und Dateiendungen
 
Bin grad über diesen Bug gestolpert.

In meinem Fall:
FindFirst('*.dpr'...) findet sowohl .dpr-Dateien als auch .dproj-Dateien.

Ist ja bizarr!

Lustigerweise ist der Bug schon sehr lang bekannt. (siehe Quality Central)
Schon komisch dass das nicht mal in der Delphi-Hilfe Erwähnung findet, damit man sich drauf einstellen kann...

Tststs....


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:52 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz