Das sollte wirklich einfach sein. Wenn ich einen String wie diesen habe:
../Test?/sample*.txt
Was ist dann ein allgemein akzeptierter Weg, um eine Liste von Dateien zu erhalten, die diesem Muster entsprechen? (zB sollte es passen ../Test1/sample22b.txt
und ../Test4/sample-spiffy.txt
aber nicht ../Test3/sample2.blah
oder ../Test44/sample2.txt
)
Ich habe es mir angesehen org.apache.commons.io.filefilter.WildcardFileFilter
und es scheint das richtige Biest zu sein, aber ich bin mir nicht sicher, wie ich es verwenden soll, um Dateien in einem relativen Verzeichnispfad zu finden.
Ich nehme an, ich kann die Quelle nach Ameise durchsuchen, da sie Wildcard-Syntax verwendet, aber mir muss hier etwas ziemlich Offensichtliches fehlen.
( Bearbeiten : Das obige Beispiel war nur ein Beispielfall. Ich suche nach einer Möglichkeit, allgemeine Pfade mit Platzhaltern zur Laufzeit zu analysieren. Ich habe anhand des Vorschlags von mmyers herausgefunden, wie das geht, aber es ist irgendwie ärgerlich. Ganz zu schweigen davon Die Java-JRE scheint einfache Platzhalter in den Hauptargumenten (String []) automatisch aus einem einzigen Argument zu analysieren, um mir Zeit und Ärger zu "sparen". Ich bin nur froh, dass ich keine Argumente außerhalb der Datei in der mischen.)
Antworten:
Betrachten Sie DirectoryScanner von Apache Ant:
Sie müssen auf ant.jar verweisen (~ 1,3 MB für ant 1.7.1).
quelle
DirectoryScanner
findet sich in Plexus-Utils (241Kb). Welches ist kleiner alsant.jar
(1,9 MB).ls
mit dem gleichenls <pattern>
Versuchen
FileUtils
von Apache commons-io (listFiles
unditerateFiles
Methoden):Um Ihr Problem mit den
TestX
Ordnern zu lösen , würde ich zuerst die Liste der Ordner durchlaufen:Eine ziemliche Brute-Force-Lösung, sollte aber gut funktionieren. Wenn dies nicht Ihren Anforderungen entspricht, können Sie jederzeit den RegexFileFilter verwenden .
quelle
Hier sind einige Beispiele für das Auflisten von Dateien durch Muster bereitgestellt von Java 7 nio Globbing und Java 8 lambdas:
oder
quelle
Files.walk(Paths.get("..")).filter(matcher::matches).forEach(System.out::println);
Sie können Ihre Platzhalterzeichenfolge in einen regulären Ausdruck konvertieren und diesen mit der
matches
Methode von String verwenden. Folgen Sie Ihrem Beispiel:Dies funktioniert für Ihre Beispiele:
Und Gegenbeispiele:
quelle
?
public static boolean isFileMatchTargetFilePattern (endgültige Datei f, endgültiger String targetPattern) {`` String regex = targetPattern.replace (".", "\\."); `regex = regex.replace("?", ".?").replace("
*", ".
*");
return f.getName().matches(regex);
}
StringBuffer regexBuffer = ...; Matcher matcher = Pattern.compile("(.*?)([*?])").matcher(original); while (matcher.find()) { matcher.appendReplacement(regexBuffer, (Pattern.quote(matcher.group(1)) + (matcher.group(2).equals("*") ? ".*?" : ".?")).replace("\\", "\\\\").replace("$", "\\$")); } matcher.appendTail(regexBuffer);
.
anstelle von ersetzt werden.?
.Seit Java 8 können Sie die
Files#find
Methode direkt von verwendenjava.nio.file
.Anwendungsbeispiel
quelle
Könnte Ihnen momentan nicht helfen, aber JDK 7 soll im Rahmen von "Weitere NIO-Funktionen" den Namen der Glob- und Regex-Dateinamen abgleichen.
quelle
Die Platzhalterbibliothek führt effizient den Abgleich von Glob- und Regex-Dateinamen durch:
http://code.google.com/p/wildcard/
Die Implementierung ist prägnant - JAR beträgt nur 12,9 Kilobyte.
quelle
Ein einfacher Weg ohne externen Import ist die Verwendung dieser Methode
Ich habe CSV-Dateien mit den Namen billing_201208.csv, billing_201209.csv, billing_201210.csv erstellt und es sieht so aus, als würde es gut funktionieren.
Die Ausgabe erfolgt wie folgt, wenn die oben aufgeführten Dateien vorhanden sind
quelle
Wie in einer anderen Antwort angegeben, funktioniert die Platzhalterbibliothek sowohl für die Übereinstimmung von Glob- als auch Regex-Dateinamen: http://code.google.com/p/wildcard/
Ich habe den folgenden Code verwendet, um Glob-Muster einschließlich absoluter und relativer Dateisysteme im * nix-Stil abzugleichen:
Ich habe einige Zeit damit verbracht, die FileUtils.listFiles-Methoden in der Apache Commons io-Bibliothek abzurufen (siehe Vladimir's Antwort), um dies zu tun, hatte aber keinen Erfolg (ich weiß jetzt / denke, dass es nur Muster verarbeiten kann, die jeweils einem Verzeichnis oder einer Datei entsprechen). .
Darüber hinaus würde die Verwendung von Regex-Filtern (siehe Fabians Antwort) zur Verarbeitung beliebiger vom Benutzer angegebener Glob-Muster vom absoluten Typ ohne Durchsuchen des gesamten Dateisystems eine Vorverarbeitung des bereitgestellten Glob erfordern, um das größte Nicht-Regex / Glob-Präfix zu bestimmen.
Natürlich kann Java 7 die angeforderte Funktionalität gut handhaben, aber leider bin ich vorerst mit Java 6 festgefahren. Die Bibliothek ist mit 13,5 KB relativ klein.
Hinweis für die Prüfer: Ich habe versucht, das oben Gesagte zu der vorhandenen Antwort hinzuzufügen, in der diese Bibliothek erwähnt wird, aber die Bearbeitung wurde abgelehnt. Ich habe auch nicht genug Repräsentanten, um dies als Kommentar hinzuzufügen. Gibt es keinen besseren Weg ...
quelle
Sie sollten in der Lage sein, die zu verwenden
WildcardFileFilter
. Verwenden Sie einfachSystem.getProperty("user.dir")
, um das Arbeitsverzeichnis zu erhalten. Versuche dies:Sie sollten nicht ersetzen müssen
*
mit der[.*]
Annahme , Wildcard - Filter verwendetjava.regex.Pattern
. Ich habe dies nicht getestet, aber ich verwende ständig Muster und Dateifilter.quelle
Glob of Java7: Suchen von Dateien . ( Probe )
quelle
Der Apache-Filter dient zum Iterieren von Dateien in einem bekannten Verzeichnis. Um Platzhalter auch im Verzeichnis zuzulassen, müssten Sie den Pfad auf '
\
' oder '/
' aufteilen und für jedes Teil einen Filter separat ausführen.quelle
Warum nicht so etwas tun wie:
Dann müssen Sie sich keine Gedanken mehr über relative Pfade machen und können Ihre Platzhalter nach Bedarf ausführen.
quelle
Implementieren Sie die JDK FileVisitor-Schnittstelle. Hier ist ein Beispiel: http://wilddiary.com/list-files-matching-a-naming-pattern-java/
quelle
Util-Methode:
Einheitentest:
Ausgabe:
quelle
foo/bar.txt
passtfoo?bar.txt
und das ist nicht richtig../Test?/sample*.txt
quelle