Laden...

Dateien filtern

Erstellt von dennisspohr vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.120 Views
dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren
Dateien filtern

Hallo,

mit Directory.GetFiles ist es möglich, mit einem SearchPattern (z.B. .txt) zu suchen. Etwas wie ".txt; *.jpg" funktioniert dabei leider nicht.
Hinzu kommt, dass ich Filter wie z.B. "hall.*t" habe. Genauso könnte es sein, dass gerade diese gefilterten Dateien NICHT gesucht / benutzt werden sollen.

Nun meine Frage: Wie kann ich die Dateien filtern? Gibts es schon etwas vorgefertigtes in .NET? Vielleicht mit Regex?

Vielen Dank!

Gruß Dennis

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo,

ich glaube ich es gerade selber hinbekommen. Bis jetzt hat es funktioniert:


        private bool FileMatchFilter(string file, string filter, bool ignoreCase)
        {
            if (ignoreCase)
            {
                file = file.ToLower();
                filter = filter.ToLower();
            }

            if (file == filter)
                return true;

            string[] searchParts = filter.Split('*');

            if ((filter[0] != '*') && (!file.StartsWith(searchParts[0])))
            {
                return false;
            }
            if ((filter[filter.Length - 1] != '*') && (!file.EndsWith(searchParts[searchParts.Length - 1])))
            {
                return false;
            }

            foreach (string searchPart in searchParts)
            {
                if (!string.IsNullOrEmpty(searchPart))
                {
                    if (!file.Contains(searchPart))
                    {
                        return false;
                    }
                }
            }

            return true;
        }

Gruß Dennis

U
1.688 Beiträge seit 2007
vor 15 Jahren

Hallo,

ich glaube ich es gerade selber hinbekommen. Bis jetzt hat es funktioniert:

vielleicht hab' ich's nicht ganz verstanden, aber warum teilst Du die Suchmuster an einem '*', nicht an einem ';'? Auch der Vergleich mit .Contains muss doch i. allg. schief gehen, oder?

Du solltest tatsächlich RegEx nehmen - ersetze dafür '' durch '.'.

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo ujr,

ich trenne den String bei einem '*', da dieses ja alles mögliche an Zeichen sein kann.
Warum sollte Contains schief laufen? Also bei mir funktioniert das Ganze. Inzwischen habe ich noch ein paar kleine Ändernungen drinne, aber nichts Großes.

Mit Regex kenne ich mich gar nicht aus.. also muss ich ein ".txt" in "..txt" umwandeln? Un dann?

Gruß Dennis

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Oh mann... wofür leicht wenn's auhc schwer geht..
Für alle die das gleiche "Problem" haben wie ich, vergesst den obigen Code, schaut euch diesen an:


        private bool FileMatchFilter(string file, string filter, bool ignoreCase)
        {
            if (ignoreCase)
            {
                file = file.ToLower();
                filter = filter.ToLower();
            }

            filter = filter.Replace("*", ".*");

            Regex regex = new Regex(filter);
            return regex.IsMatch(file);
        } 

ujr ich danke dir!

Gruß Dennis

U
1.688 Beiträge seit 2007
vor 15 Jahren

Hallo,

ich trenne den String bei einem '*', da dieses ja alles mögliche an Zeichen sein kann.
Warum sollte Contains schief laufen? Also bei mir funktioniert das Ganze. Inzwischen habe ich noch ein paar kleine Ändernungen drinne, aber nichts Großes.

Mit Regex kenne ich mich gar nicht aus.. also muss ich ein ".txt" in "..txt" umwandeln? Un dann?

Ah - ja. Jetzt hab' ich wohl Deinen Algorithmus richtig verstanden 🙂

Ich bin von Deinem Suchmuster "*.txt; .jpg" ausgegangen. Dieses müsste ja am ';' getrennt werden. Anschließend werden die einzelnen Suchmuster angewandt, so wie Du es schon gemacht hast.
.Contains hilft dann nicht, wenn die einzelnen Teilstrings im Zielstring in anderer Reihenfolge auftreten, also:
Muster: Teil1Teil2
.txt
Dateiname: Teil3Teil2Teil1Teil0.txt

Zu den RegEx - Dein Beispiel ".txt" würde korrekterweise diesem RegEx entsprechen: "..txt", der '.' muss also noch als Sonderzeichen maskiert werden. Das beträfe natürlich auch andere Sonderzeichen wie runde und eckige Klammern. Schau Dir am besten dazu mal das RegEx-Tutorial im Artikel-Forum an.

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo ujr,

.Contains hilft dann nicht, wenn die einzelnen Teilstrings im Zielstring in anderer Reihenfolge auftreten, also:
Muster: Teil1Teil2*.txt
Dateiname: Teil3Teil2Teil1Teil0.txt

dazu sag ich nur folgendes:

Inzwischen habe ich noch ein paar kleine Ändernungen drinne

*grins*

der '.' muss also noch als Sonderzeichen maskiert werden

Das verstehe ich nicht. Warum muss der '.' als Sonderzeichen maskiert werden? Ein Punkt kann doch im jeden Dateinamen auftauchen.. ?

Das beträfe natürlich auch andere Sonderzeichen wie runde und eckige Klammern

Das wird nie passieren, weil der Methode nur gültige Dateinamen übergeben werden.

Gruß Dennis

U
1.688 Beiträge seit 2007
vor 15 Jahren

Hallo,

der Punkt in einem RegEx steht für jedes beliebige Zeichen (oder auch keins). Wenn Du also tatsächlich einen Punkt haben möchtest, musst Du ihn im RegEx maskieren.

Runde und eckige Klammern sind in gültigen Dateinamen möglich und auch gar nicht so unwahrscheinlich. Da sie für RegEx eine besondere Bedeutung haben, müssen sie auch maskiert werden, wenn sie im Filterstring auftreten.

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo ujr,

achso okay. Das ist schlecht 🙂

Runde und eckige Klammern sind in gültigen Dateinamen möglich und auch gar nicht so unwahrscheinlich

Stimmt, hast Recht.

Ich werde mir das Ganze mal anschauen. Vielen Dank für deine Hilfe, hast mir sehr weitergeholfen!

Gruß Dennis

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

So, fertig:


        private bool FileMatchFilter(string file, string filter, bool ignoreCase)
        {
            if (string.IsNullOrEmpty(file))
                return true;

            if (string.IsNullOrEmpty(filter))
                return true;

            if (ignoreCase)
            {
                file = file.ToLower();
                filter = filter.ToLower();
            }

            if ((filter[0] != '*') && (!file.StartsWith(filter.Split('*')[0])))
                return false;

            if ((filter[filter.Length - 1] != '*') && (!file.EndsWith(filter.Split('*')[filter.Split('*').Length - 1])))
                return false;
            
            filter = filter.Replace("*", ".*");
            filter = filter.Replace(".", "\\.");
            filter = filter.Replace("(", "\\(");
            filter = filter.Replace(")", "\\)");
            filter = filter.Replace("[", "\\[");
            filter = filter.Replace("]", "\\]");

            Regex regex = new Regex(filter);
            return regex.IsMatch(file);
        }

🙂

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo dennisspohr,

filter = filter.Replace("*", ".*");
...

verwende besser Regex.Escape.

herbivore

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo herbivore,

habe ich gemacht 🙂
Danke!

Gruß Dennis