Avec le JFileChooser de Swing il est possible d’ajouter des FileFilter pour filtrer la liste de fichiers affichés.
Cet article va décrire un FileFilter personalisé capable de filtrer selon plusieurs extensions de fichiers. Cela peut être utile si un format de fichier peut avoir plusieurs extensions ou si on souhaite regrouper plusieurs extensions sous un même nom (ex: images, sons, archives ).
Nous allons appeller la nouvelle classe MultipleFileFilter (en opposition avec Simple) dont les attributs sont description et un array pour reprendre plusieurs extensions de fichiers.
private String description;
private String[] extensions;
Le tout sera initialisé à travers ce constructeur. Le code utilisant un StringBuffer a pour but d’ajouter une liste des extensions à la description.
if (description == null || extensions == null) {
throw new IllegalArgumentException(
"The filter description or file name extensions cannot be null.");
}
this.extensions = extensions;
StringBuffer sb = new StringBuffer("(");
for( String s : extensions ){
sb.append("*");
sb.append(s);
if( !s.equals(extensions[extensions.length-1]) ){
sb.append(",");
}
}
sb = sb.append(")");
this.description = description + " " + sb.toString();
}
Nous en venons ensuite à la méthode accept qui décide si un fichier est pris en compte ou pas. Rien de complex. On va tout simplement prendre le nom d’un fichier et vérifier dans la boucle si son extension correspond à l’un des valeurs reprises dans l’array. S’il y a une correspondance une valeur true sera renvoyée ce qui indiquera au JFileChooser qu’un fichier a été accepté.
if (file.isDirectory()) {
return true;
}
String nomFichier = file.getName().toLowerCase();
for( String extension : extensions ){
if(nomFichier.endsWith(extension)){
return true;
}
}
return false;
}
Voila, j’espère que cette petite classe vous sera utile pour vos propres créations.
– James Poulson.
Le
est une collection triée d’objets uniques.
Dans ton cas d’utilisation (chercher dans la collection si un élément existe), le fait qu’elle soit triée a tout sont intérêt, cela rend plus facile la recherche d’un élément.
Par exemple, avec les extensions « bmp », « gif », « jpg », « png », « tif ».
Si on recherche l’extension « tif », en utilisant le parcours simple du tableau, complexité O(n), cela nécessiterait de le parcourir dans son intégralité soit 5 itérations.
En utilisant une collection triée, avec un algo du genre dichotomie, complexité O(log(n)), le nombre d’itération tombe à 2 ou 3.
Pour t’aider à comprendre la notation de la complexité en O, pense aux courbes des fonctions.
En abscisse tu as le « n » qui représente ce que tu « demandes » à l’algorithme et l’ordonnée représente le nombre d’itération qu’il effectuera.
Donc pour la complexité O(n) (imagine la courbe d’une fonction f(n) = n ) ça te donne une droite qui augment linéairement. Donc plus tu demandes à l’algo, plus cela va coûter en perfs et ce de façon linéaire.
Maintenant pour la complexité O(log(n)), visualise la fonction log(n). Au début ça monte un peu linéairement mais que plus n augmente moins la courbe monte et elle tend à se stabiliser. Une complexité O(log(n)) est donc mieux qu’une complexité O(n).
Inversement prend une complexité O(n²), la courbe n² augmente beaucoup plus rapidement que la courbe n, la complexité O(n²) est donc supérieure.
Superpose les courbes sur un même graphe ça devrait t’aider à mieux visualiser
Donc pour en revenir à la méthode
du
, la javadoc confirme que sa complexité est en O(log(n)) ce qui est nettement plus performant que le parcours systématique d’un tableau de complexité O(n) ;).
Bonsoir,
Merci pour les suggestions. En effet, tel qu’était écrit le code le endsWith provoque une sortie prématurée de la boucle. Pour le reste, je ne suis pas familier avec la collection SortedSet. Existe t-il une référence qui compare les performances de différentes structures ? Aussi, j’essaye de m’y faire à la notation O pour la comparaison des algorithmes mais ce n’est pas encore gagné
Je pense qu’il y a une erreur dans ton code. En effet, si l’extension du fichier n’est pas la première du tableau alors ta méthode
renverra toujours
. Le code serait plutôt :
for( String extension : extensions ){ <br />
if(nomFichier.endsWith(extension)) { <br />
return true; <br />
} <br />
} <br />
return false; <br />
Ensuite il serait peut être plus performant d’utiliser un
pour stocker les extensions puis pour le test de récupérer l’extension sur le nom du fichier et faire un simple
.
private final SortedSet extensions = new TreeSet(); <br />
<br />
public MultipleExtensionFileFilter(String description, String... extensions) { <br />
this.extensions.addAll(Arrays.asList(extensions)); // De base les valeurs null ne sont pas permises pas le TreeSet <br />
<br />
StringBuilder sb = new StringBuilder(description).append(" ("); <br />
for( String s : extensions ){ <br />
sb.append("*").append(s).append(","); <br />
} <br />
sb.replace(sb.length() - 1, sb.length(), ")"); // remplacement du dernier ',' par ')' <br />
this.description = sb.toString(); <br />
} <br />
<br />
public boolean accept(File file) { <br />
if (file.isDirectory()) { <br />
return true; <br />
} <br />
String nomFichier = file.getName().toLowerCase(); <br />
int index = nomFichier.lastIndexOf("."); <br />
String extension = index < 0 ? "" : nomFichier.substring(index + 1); <br />
return extensions.contains(extension); <br />
} <br />