Datei Filter



  • Z.B bim Öffnen Dialog gibt es die Möglichkeit einen Filter zu spezifizieren. Sowas wie *.jpg, *.bmp usw.

    In meinem Programm benötige ich eine ähniche Funktion, also ich bekomme eine Datei(namen) und ich muss wissen ob er in diesen Filter "passt".

    Gibt es da was vorgefertigtes, oder "darf" 🙄 ich mich da selber ranmachen?



  • Hallo,

    da darfst du dich selbst ranmachen. Aber Funktionen wie "ExtractFileExt()" sollten die Angelegenheit recht einfach gestalten.

    LG, Micha



  • Ich probiere mich nun schon seit eingiger Zeit diesen Suchfilter efizient zu gestalten. Aber leider erweist sich schon ein einfacher Vergleich (ohne die Verwendung von * und ?) schon als derart inperformant, dass sich das ganze sehr negativ auf die Programmlaufzeit auswirkt.

    Hintergrund: Kopieroperation bei der einige Dateitypen ausgeklammert werden sollen (z.B. *.tmp). Momentan ist es jedoch schneller alle Dateien zu kopieren als den Filter anzuwenden, was irgendwie ja nicht sein darf... 😡

    Weiß jemand noch Rat?



  • Hallo

    Ich kann mir kaum vorstellen, das ein einfacher String-Vergleich im Vergleich zum Kopieren so viel Zeit kosten soll. Zeig doch mal konkreten relevanten Quellcode.

    bis bald
    akari



  • Der Vergleich liegt in einer eigenen Funktion:

    Es existieren 2 String-Listen, die jeweils Dateiname und erweiterung beinhalten, es hat sich herausgestellt dass dies performater ist als die "Einzelteile"jedes mal zu berechnen.

    TStringList * filterFn;
    TStringList * filterFe;
    
    bool __fastcall TFormXXXX::CheckIfFilter(String fileName)
    {
    	String fn = ExtractFileName(fileName);
    	String fe = ExtractFileExt(fileName);
    
    	// true wenn der filter passt
    	for (int i = 0; i < filterFn->Count; i++)
    	{
    		String n = filterFn->Strings[i];
    		String e = filterFe->Strings[i];
    
    		if ( ((n == "*" || n == fn)) && ((e == "*" || e == fe)))
    		{
    			return true;
    		}
    	}
    	return false;
    }
    


  • Hallo

    Wieviele Elemente stehen denn in filterFn und filterFe so drin?
    Zwei Vorschläge hätte ich schonmal :
    - Du prüfst bei jedem Durchgang auf == "*", obwohl das ja einmalig am Anfang gepfrüft werden kann. Prinzip :

    String fn = ExtractFileName(fileName);
    bool fn_p = (fn == "*");
    ...
    if (fn_p || n == fn)
    ...
    

    - Desweiteren solltest du ansteller einer TStringList ein std::set<String> nehmen, um die Filter zu verwalten. Vorteil : Die in std::set eingebaute Suchfunktion erspart dir nicht nur die manuelle Schleife, sondern arbeitet auch schneller als eine Schleife, je mehr Filter du hast.

    bis bald
    akari



  • Die Anzahl der Filterelemente ist variabel, würde sagen typischerweise zwischen keinem und ca. 10 Stück.

    Das mit dem set könnte eine Möglichkeit sein, werde ich prüfen und testen, Danke dafür erstmal.

    Das mit dem "" wird aber nicht klappen denke ich, denn ich prüfe ja den Filter auf "" und der ist bei jedem durchlauf ein anderer.

    Grüße
    Anton



  • Hallo

    Das mit dem "" wird aber nicht klappen denke ich, denn ich prüfe ja den Filter auf "" und der ist bei jedem durchlauf ein anderer.

    Ich meine damit, das du vor dem Vergleich von einem ganzen Haufen Dateien (du rufst ja für jede Datei CheckIfFilter auf) erstmal schauen solltest, ob in filterFn oder in filterFe überhault ein * steckt. Denn wenn ja, kannst du dir das Prüfen der Dateinamen bzw. der Erweiterung ganz sparen. Am besten trennst du die Funktion auf (Pseudocode) :

    bool PrüfeObPlatzhalterVorhanden(FilterListe)
    {
      return Mindestens_ein_Element_ist_Platzhalter(FilterListe);
    }
    
    bool NamePasstInFilter(String Name)
    {
      return Name_und_nur_Name_prüfen(Name);
    }
    
    bool ErweiterungPasstInFilter(String Name)
    {
      return Erweiterung_und_nur_Erweiterung_prüfen(Name);
    }
    
    // Ein Durchgang
    ...
    Dateien // Deine Liste mit den zu prüfenden Dateinamen
    bool Name_relevant = PrüfeObPlatzhalterVorhanden(filterFn);
    bool Erweiterung_relevant = PrüfeObPlatzhalterVorhanden(filterFe);
    
    Für jeden Namen in Dateien
    {
      Wenn ((!Name_relevant || NamePasstInFilter(Name)) && 
        ((!Erweiterung_relevant || ErweiterungPasstInFilter(Name)))
      {
        VerarbeiteDatei(Name) // Name passt in Filter 
      }
    }
    

    Vorteil : Wenn mindestens Name oder Erweiterung durch ein Platzhalter gefiltert werden, sparst du dir eine ganze Hälfte der Vergleichsarbeit. Wenn sowohl Name als auch Erweiterung mindestens einen Platzhalter beinhalten, fällt der Vergleich mit den Filtern gleich ganz weg.

    Desweiteren solltest du auch noch überlegen, das Zerteilen des Dateinamens selber zu übernehmen. Denn ExtractFileName als auch ExtractFileExt machen fasst dasselbe : Sie suchen nach einem '.' im String. Wenn also kein Platzhalter vorhanden ist und Name als auch Erweiterung geprüft werden, wird ein Dateiname zweimal zerlegt. Mit einer manuellen Zerlegung kannst du dir beide Teile in einem Arbeitsschritt liefern lassen.

    bis bald
    akari


Anmelden zum Antworten