Comment trouver des fichiers qui correspondent à une chaîne de caractères en Java?
cela devrait être vraiment simple. Si j'ai une chaîne comme celle-ci:
../Test?/sample*.txt
alors quelle est une façon généralement acceptée d'obtenir une liste de fichiers qui correspondent à ce modèle? (par exemple, il doit correspondre à ../Test1/sample22b.txt
et ../Test4/sample-spiffy.txt
mais pas à ../Test3/sample2.blah
ou ../Test44/sample2.txt
)
j'ai jeté un oeil à org.apache.commons.io.filefilter.WildcardFileFilter
et il semble comme la bonne bête, mais je ne sais pas comment l'utiliser pour trouver des fichiers dans un répertoire relatif chemin.
je suppose que je peux chercher la source pour ant puisqu'il utilise la syntaxe de Joker, mais je dois manquer quelque chose assez évident ici.
( edit : l'exemple ci-dessus n'était qu'un cas type. Je cherche le moyen de parcourir les chemins généraux contenant des caractères génériques à l'exécution. J'ai trouvé comment le faire en me basant sur la suggestion de mmyers mais c'est un peu agaçant. Sans oublier que le java JRE semble auto-analyser des jokers simples dans le main (String[] arguments) à partir d'un seul argument pour me "sauver" le temps et les tracas... Je suis juste content de ne pas avoir d'arguments non-classés dans le mix.)
15 réponses
Envisager DirectoryScanner de Apache Ant:
DirectoryScanner scanner = new DirectoryScanner();
scanner.setIncludes(new String[]{"**/*.java"});
scanner.setBasedir("C:/Temp");
scanner.setCaseSensitive(false);
scanner.scan();
String[] files = scanner.getIncludedFiles();
vous devez faire référence à ant.jar (~1.3 MB pour ant 1.7.1).
Essayer FileUtils
à partir de Apache commons-io ( listFiles
et iterateFiles
méthodes):
File dir = new File(".");
FileFilter fileFilter = new WildcardFileFilter("sample*.java");
File[] files = dir.listFiles(fileFilter);
for (int i = 0; i < files.length; i++) {
System.out.println(files[i]);
}
pour résoudre votre problème avec les dossiers TestX
, je voudrais d'abord itérer à travers la liste des dossiers:
File[] dirs = new File(".").listFiles(new WildcardFileFilter("Test*.java");
for (int i=0; i<dirs.length; i++) {
File dir = dirs[i];
if (dir.isDirectory()) {
File[] files = dir.listFiles(new WildcardFileFilter("sample*.java"));
}
}
tout à fait une solution de "force brute" mais devrait fonctionner très bien. Si cela ne correspond pas à vos besoins, vous pouvez toujours utiliser le RegexFileFilter .
Voici des exemples de listes de fichiers par modèle alimenté par Java 7 nio globbing et Java 8 lambdas:
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(
Paths.get(".."), "Test?/sample*.txt")) {
dirStream.forEach(path -> System.out.println(path));
}
ou
PathMatcher pathMatcher = FileSystems.getDefault()
.getPathMatcher("regex:Test.[\/]sample\w+\.txt");
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(
new File("..").toPath(), pathMatcher::matches)) {
dirStream.forEach(path -> System.out.println(path));
}
vous pouvez convertir votre chaîne de caractères génériques en une expression régulière et utiliser la méthode matches
de String. Suivant votre exemple:
String original = "../Test?/sample*.txt";
String regex = original.replace("?", ".?").replace("*", ".*?");
cela fonctionne pour vos exemples:
Assert.assertTrue("../Test1/sample22b.txt".matches(regex));
Assert.assertTrue("../Test4/sample-spiffy.txt".matches(regex));
et contre-exemples:
Assert.assertTrue(!"../Test3/sample2.blah".matches(regex));
Assert.assertTrue(!"../Test44/sample2.txt".matches(regex));
pourrait ne pas vous aider en ce moment, mais JDK 7 est destiné à avoir le nom de fichier glob et regex correspondant dans le cadre de"plus de fonctionnalités NIO".
depuis Java 8, Vous pouvez utiliser la méthode Files#find
directement à partir de java.nio.file
.
public static Stream<Path> find(Path start,
int maxDepth,
BiPredicate<Path, BasicFileAttributes> matcher,
FileVisitOption... options)
exemple d'usage
Files.find(startingPath,
Integer.MAX_VALUE,
(path, basicFileAttributes) -> path.toFile().getName().matches(".*.pom")
);
la bibliothèque wildcard fait efficacement la correspondance des noms de fichiers glob et regex:
http://code.google.com/p/wildcard /
l'implémentation est succincte -- JAR n'est que de 12,9 kilo-octets.
méthode Simple sans utiliser d'importation externe est d'utiliser cette méthode
j'ai créé des fichiers csv nommés avec billing_201208.csv, billing_201209.csv, billing_201210.csv et il semble bien fonctionner.
sortie sera la suivante si les fichiers énumérés ci-dessus existe
found billing_201208.csv
found billing_201209.csv
found billing_201210.csv
//Use Import ->import java.io.File public static void main(String[] args) { String pathToScan = "."; String target_file ; // fileThatYouWantToFilter File folderToScan = new File(pathToScan);File[] listOfFiles = folderToScan.listFiles(); for (int i = 0; i < listOfFiles.length; i++) { if (listOfFiles[i].isFile()) { target_file = listOfFiles[i].getName(); if (target_file.startsWith("billing") && target_file.endsWith(".csv")) { //You can add these files to fileList by using "list.add" here System.out.println("found" + " " + target_file); } } } }
comme posté dans une autre réponse, la bibliothèque wildcard fonctionne à la fois pour glob et regex correspondance de nom de fichier: http://code.google.com/p/wildcard /
j'ai utilisé le code suivant pour faire correspondre les motifs glob incluant absolu et relatif sur les systèmes de fichiers de style nix:
String filePattern = String baseDir = "./";
// If absolute path. TODO handle windows absolute path?
if (filePattern.charAt(0) == File.separatorChar) {
baseDir = File.separator;
filePattern = filePattern.substring(1);
}
Paths paths = new Paths(baseDir, filePattern);
List files = paths.getFiles();
j'ai passé du temps à essayer d'obtenir les FileUtils.méthodes listFiles dans la bibliothèque io d'Apache commons (voir la réponse de Vladimir) pour faire ceci mais n'avait pas succès (je réalise maintenant/je pense qu'il ne peut gérer que le motif correspondant à un répertoire ou à un fichier à la fois).
de plus, l'utilisation de filtres regex (voir la réponse de Fabian) pour le traitement des motifs de type absolu fournis par l'utilisateur sans effectuer de recherche dans l'ensemble du système de fichiers nécessiterait un prétraitement de la glob fournie pour déterminer le plus grand préfixe Non-regex/glob.
bien sûr, Java 7 peut gérer la fonctionnalité demandée correctement, mais malheureusement, je suis coincé avec Java 6 pour l'instant. La bibliothèque est relativement minuscule à 13,5 ko.
Note aux réviseurs: j'ai essayé d'ajouter la réponse ci-dessus à la réponse existante mentionnant cette bibliothèque, mais l'édition a été rejetée. Je n'ai pas assez de réputation pour ajouter ceci comme commentaire. N'est-il pas une meilleure façon...
vous devriez pouvoir utiliser le WildcardFileFilter
. Suffit d'utiliser System.getProperty("user.dir")
pour obtenir le répertoire de travail. Essayez ceci:
public static void main(String[] args) {
File[] files = (new File(System.getProperty("user.dir"))).listFiles(new WildcardFileFilter(args));
//...
}
vous ne devriez pas avoir à remplacer *
par [.*]
, en supposant que le filtre de Joker utilise java.regex.Pattern
. Je n'ai pas testé cela, mais j'utilise des modèles et des filtres de fichiers constamment.
Glob de Java7: recherche de Fichiers . ( échantillon )
le filtre Apache est construit pour itérer des fichiers dans un répertoire connu. Pour permettre les caractères génériques dans le répertoire aussi, vous devez diviser le chemin sur ' \
' ou ' /
' et faire un filtre sur chaque partie séparément.
Pourquoi ne pas faire quelque chose comme:
File myRelativeDir = new File("../../foo");
String fullPath = myRelativeDir.getCanonicalPath();
Sting wildCard = fullPath + File.separator + "*.txt";
// now you have a fully qualified path
alors vous n'aurez pas à vous soucier des chemins relatifs et pouvez faire votre wildcarding si nécessaire.
implémenter l'interface JDK FileVisitor. Voici un exemple http://wilddiary.com/list-files-matching-a-naming-pattern-java/
Méthode Util:
public static boolean isFileMatchTargetFilePattern(final File f, final String targetPattern) {
String regex = targetPattern.replace(".", "\."); //escape the dot first
regex = regex.replace("?", ".?").replace("*", ".*");
return f.getName().matches(regex);
}
test de jUnit:
@Test
public void testIsFileMatchTargetFilePattern() {
String dir = "D:\repository\org\my\modules\mobile\mobile-web\b1605.0.1";
String[] regexPatterns = new String[] {"_*.repositories", "*.pom", "*-b1605.0.1*","*-b1605.0.1", "mobile*"};
File fDir = new File(dir);
File[] files = fDir.listFiles();
for (String regexPattern : regexPatterns) {
System.out.println("match pattern [" + regexPattern + "]:");
for (File file : files) {
System.out.println("\t" + file.getName() + " matches:" + FileUtils.isFileMatchTargetFilePattern(file, regexPattern));
}
}
}
sortie:
match pattern [_*.repositories]:
mobile-web-b1605.0.1.pom matches:false
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:true
match pattern [*.pom]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:false
match pattern [*-b1605.0.1*]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:true
_remote.repositories matches:false
match pattern [*-b1605.0.1]:
mobile-web-b1605.0.1.pom matches:false
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:false
match pattern [mobile*]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:true
_remote.repositories matches:false