173 votes

Comment trouver les fichiers qui correspondent à une chaîne de caractères génériques en Java ?

Cela devrait être très simple. Si j'ai une chaîne comme ceci :

../Test?/sample*.txt

alors quelle est la méthode généralement acceptée pour obtenir une liste des fichiers qui correspondent à ce modèle ? (par exemple, il devrait correspondre à ../Test1/sample22b.txt y ../Test4/sample-spiffy.txt mais pas ../Test3/sample2.blah ou ../Test44/sample2.txt )

J'ai jeté un coup d'oeil à org.apache.commons.io.filefilter.WildcardFileFilter et cela semble être la bonne bête mais je ne suis pas sûr de savoir comment l'utiliser pour trouver des fichiers dans un chemin de répertoire relatif.

Je suppose que je peux regarder la source pour ant puisqu'il utilise la syntaxe des caractères génériques, mais je dois manquer quelque chose de très évident ici.

( modifier l'exemple ci-dessus n'était qu'un cas d'école. Je cherche un moyen d'analyser les chemins généraux contenant des caractères génériques au moment de l'exécution. J'ai trouvé comment le faire en me basant sur la suggestion de mmyers mais c'est un peu ennuyeux. Sans parler du fait que le JRE java semble analyser automatiquement les caractères génériques simples dans le main(String[] arguments) à partir d'un seul argument pour m'épargner du temps et des soucis... Je suis juste content de ne pas avoir eu d'arguments non-fichiers dans le mélange).

2 votes

C'est le shell qui analyse les caractères génériques, pas Java. Vous pouvez les échapper, mais le format exact dépend de votre système.

2 votes

Non, ça ne l'est pas. Windows n'analyse pas les caractères génériques *. J'ai vérifié cela en exécutant la même syntaxe sur un fichier batch fictif et en affichant l'argument #1 qui était Test/*.obj pointant vers un répertoire rempli de fichiers .obj. Le résultat est "Test/*.obj". Java semble faire quelque chose de bizarre ici.

0 votes

Huh, vous avez raison ; presque toutes les commandes intégrées à l'interpréteur de commandes développent les caractères génériques, mais l'interpréteur de commandes lui-même ne le fait pas. Quoi qu'il en soit, vous pouvez simplement mettre l'argument entre guillemets pour empêcher Java d'analyser les caractères génériques : java MyClass "Test/*.obj"

136voto

Vladimir Points 4511

Essayez FileUtils de Apache commons-io ( listFiles y 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 le TestX je commencerais par itérer dans 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"));
   }
}

Il s'agit d'une solution de force brute, mais elle devrait fonctionner correctement. Si cela ne répond pas à vos besoins, vous pouvez toujours utiliser la fonction RegexFileFilter .

2 votes

Ok, maintenant tu es arrivé exactement là où était Jason S quand il a posté la question.

0 votes

Pas tout à fait. Il y a aussi le RegexFileFilter qui peut être utilisé (mais personnellement je n'en ai jamais eu besoin).

85voto

Misha Points 926

Considérez 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 devrez référencer ant.jar (~ 1,3 Mo pour ant 1.7.1).

1 votes

Excellent ! btw, scanner.getIncludedDirectories() fait la même chose si vous avez besoin de répertoires. (getIncludedFiles ne fonctionnera pas)

1 votes

Le projet wildcard sur github fonctionne également comme un charme : github.com/EsotericSoftware/wildcard

1 votes

@Moreaki, cela doit être une réponse séparée, pas un commentaire.

30voto

Fabian Steeg Points 24261

Vous pouvez convertir votre chaîne de caractères génériques en une expression régulière et l'utiliser avec la fonction de String matches méthode. En 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 des contre-exemples :

Assert.assertTrue(!"../Test3/sample2.blah".matches(regex));
Assert.assertTrue(!"../Test44/sample2.txt".matches(regex));

3 votes

Cela ne fonctionnera pas pour les fichiers qui contiennent des caractères spéciaux de regex comme (, + ou $.

0 votes

J'ai utilisé 'String regex = "^" + s.replace(" ? ", ". ?").replace(" ", ". ?") + "$"' (Les astérisques ont disparu dans mon commentaire pour une raison quelconque...)

2 votes

Pourquoi remplacer * par '.* ? ? public static boolean isFileMatchTargetFilePattern(final File f, final String targetPattern) {` ` String regex = targetPattern.replace(".", " \\. ");` regex = regex.replace("?", ".?").replace(" * ", ". * "); return f.getName().matches(regex); }

18voto

Cela ne vous aidera peut-être pas pour l'instant, mais le JDK 7 est censé disposer de la correspondance des noms de fichiers glob et regex dans le cadre de "More NIO Features".

3 votes

En Java 7 : Files.newDirectoryStream( path, glob-pattern )

13voto

NateS Points 1528

La bibliothèque de caractères génériques permet de faire correspondre efficacement les noms de fichiers globaux et regex :

http://code.google.com/p/wildcard/

L'implémentation est succincte : le JAR ne fait que 12,9 kilo-octets.

2 votes

Le seul inconvénient est qu'il ne se trouve pas dans Maven Central.

3 votes

C'est un logiciel libre, allez-y et mettez-le sur Maven Central :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X