Un Filefilter reprenant plusieurs extensions de fichier

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.

public class MultipleFileFilter extends FileFilter {
 
  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.

  public MultipleExtensionFileFilter(String description, String[] extensions) {
    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é.

  public boolean accept(File file) {
    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.

15 réflexions au sujet de « Un Filefilter reprenant plusieurs extensions de fichier »

  1. Le

    SortedSet

    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

    contains()

    du

    SortedSet

    , 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) ;).

  2. 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é :)

  3. 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

    accept

    renverra toujours

    false

    . Le code serait plutôt :

    &nbsp;<br />
    for( String extension : extensions ){ &nbsp;<br />
    &nbsp;   if(nomFichier.endsWith(extension)) {&nbsp;<br />
    &nbsp;       return true;&nbsp;<br />
    &nbsp;   }&nbsp;<br />
    }     &nbsp;<br />
    return false; &nbsp;<br />

    Ensuite il serait peut être plus performant d’utiliser un

    SortedSet

    pour stocker les extensions puis pour le test de récupérer l’extension sur le nom du fichier et faire un simple

    contains()

    .

    &nbsp;<br />
    private final SortedSet extensions = new TreeSet();&nbsp;<br />
    &nbsp;<br />
    public MultipleExtensionFileFilter(String description, String... extensions) {&nbsp;<br />
    &nbsp;   this.extensions.addAll(Arrays.asList(extensions)); // De base les valeurs null ne sont pas permises pas le TreeSet&nbsp;<br />
    &nbsp;   &nbsp;<br />
    &nbsp;   StringBuilder sb = new StringBuilder(description).append(" ("); &nbsp;<br />
    &nbsp;   for( String s : extensions ){ &nbsp;<br />
    &nbsp;     sb.append("*").append(s).append(","); &nbsp;<br />
    &nbsp;   } &nbsp;<br />
    &nbsp;   sb.replace(sb.length() - 1, sb.length(), ")"); // remplacement du dernier ',' par ')'&nbsp;<br />
    &nbsp;   this.description = sb.toString(); &nbsp;<br />
    &nbsp; }&nbsp;<br />
    &nbsp;<br />
    &nbsp; public boolean accept(File file) { &nbsp;<br />
    &nbsp;   if (file.isDirectory()) { &nbsp;<br />
    &nbsp;     return true; &nbsp;<br />
    &nbsp;   } &nbsp;<br />
    &nbsp;   String nomFichier = file.getName().toLowerCase(); &nbsp;<br />
    &nbsp;   int index = nomFichier.lastIndexOf(".");&nbsp;<br />
    &nbsp;   String extension = index &lt; 0 ? "" : nomFichier.substring(index + 1);&nbsp;<br />
    &nbsp;   return extensions.contains(extension);&nbsp;<br />
    &nbsp; }&nbsp;<br />

Les commentaires sont fermés.