IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

FileFilter générique type linux


Sujet :

Entrée/Sortie Java

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Février 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Février 2007
    Messages : 80
    Points : 76
    Points
    76
    Par défaut FileFilter générique type linux
    Bonjour,

    Pour les besoins d'une application qui toune sous GNU/Linux, j'ai écrit une classe ArgFilter qui implémente java.io.FileFilter pour filtrer des noms de fichiers de la facon la plus générale qui soit.
    Je cherche à reproduire le même genre de filtre d'argument qu'offre la commande ls en linux : un filtre du genre *iMg*.nc

    J'ai un petit code qui à l'air de marcher.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    //////////////////////////////////////////////
      public class ArgFilter implements java.io.FileFilter {
     
        private String filter;
        private String[] splitFilter;
        private int nbPattern;
        private boolean allFiles;
     
        //------------------------------
        public ArgFilter(String arg) {
          filter = arg;
          allFiles = filter.equals("*.*") || filter.equals("*");
          splitFilter = filter.split("\\*");
          nbPattern = splitFilter.length;
        }
     
        //-----------------------------
        public boolean accept(File f) {
     
          // Return false if directory
          if (!f.isFile()) return false;
          // Return true if "*.*"
          if (allFiles) return true;
          String n = f.getName();
          // Return false if file length smaller than filter length
          if (n.length() < filter.length()) return false;
          String pattern = splitFilter[0];
          // Process first and last patterns in case they are not "*"
          if (pattern != null && !n.startsWith(pattern)) return false;
          if (!filter.endsWith("*") && !n.endsWith(splitFilter[nbPattern - 1])) return false;
          String subn;
          // Process other patterns
          int k = (pattern != null) ? pattern.length() : 0;
          for (int i = 1; i < nbPattern; i++) {
            pattern = splitFilter[i];
            if (pattern != null) {
              subn = n.substring(k);
              if (subn.contains(pattern)) k = subn.indexOf(pattern) + pattern.length();
              else return false;
            }
          }
          // Eventually return true
          return true;
        }
      }
    Que j'utilise de la façon suivante, par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    File inputPath = new File("/lib/");
    File[] listFile = inputPath.listFiles(new ArgFilter("li*mca*"));
    for (File file : listFile) System.out.print(file.getName() + " ");
    Je le soumets simplement à vos critiques et commentaires. Est-ce la bonne façon de s'y prendre ? Comment l'améliorer ? Toutes remarques bienvenues !
    Merci d'avance
    Philippe.

  2. #2
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Pattern + Matcher ou comment utiliser les regex en java
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  3. #3
    Membre régulier
    Homme Profil pro
    Inscrit en
    Février 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Février 2007
    Messages : 80
    Points : 76
    Points
    76
    Par défaut
    Merci Sinok !
    Pour le coup c'est moi qui suis bien pourrave ... je ne connaissais pas les regex, les matchers, etc.

    Merci pour ces liens, pas facile quand même d'apréhender les Regex !
    J'ai reécrit ma classe ArgFilter en utilisant simplement un String.matches() dans la méthode Filefilter.accept().
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    public class ArgFilter implements FileFilter {
     
        private String pattern;
     
        //------------------------------
        public ArgFilter(String arg) {
          // Transform the argument into regex with reluctant quantifiers
          pattern = arg.replaceAll("\\*", "(\\.\\*\\?)");
          System.out.println(pattern);
        }
     
        //-----------------------------
        public boolean accept(File f) {
     
          // Return false if directory
          if (!f.isFile()) return false;
          // Return true if file name matche the pattern
          return f.getName().matches(pattern);
        }
      }
    Dans le constructeur je remplace tous les charactères * de l'argument par l'expression regulière (.*?) pour avoir le bon pattern.
    Ca a l'air de marcher. Sinok, c'est bien par là que tu voulais m'orienter ?
    J'utilise un Reluctant quantifier, mais j'ai du mal à comprendre ce qu'implique l'utilisation de l'un ou l'autre des quantifiers ...

    Encore merci. Philippe.

  4. #4
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Points : 5 943
    Points
    5 943
    Par défaut
    adiGuba a posté le source d'un FilenameFilter faisant ce que tu veux (ici), tu doit pouvoir l'adapter à un FileFilter .
    Je ne répondrai à aucune question technique par MP.

    Pensez aux Tutoriels et aux FAQs avant de poster (pour le java il y a aussi JavaSearch), n'oubliez pas non plus la fonction Rechercher.
    Enfin, quand une solution a été trouvée à votre problème
    pensez au tag

    Cours Dvp : http://ydisanto.developpez.com
    Blog : http://yann-disanto.blogspot.com/
    Page perso : http://yann-disanto.fr

  5. #5
    Membre régulier
    Homme Profil pro
    Inscrit en
    Février 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Février 2007
    Messages : 80
    Points : 76
    Points
    76
    Par défaut
    Ok, merci pour le lien, c'est exactement ce que je cherchais à faire. J'ai mal cherché sur le forum, je n'avais pas vu son post...
    Je suis bon pour un petit délestage.

    Mon code ressemble sensiblement à celui proposé par adiGuba, sauf que je ne tenais pas compte du métacharactère ?.

    Il utilise un Greedy quantifier là ou j'utilise un Reluctant qualifier. Je ne vois pas très bien ce que ça implique concrètement, l'explication de la javadoc et du tuto ne m'éclairent pas vraiment.

    Merci M. le Yam's ! Philippe.

    J'ai parlé un peu vite, j'ai une erreur à l'éxecution du code d'adiGuba
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    Exception in thread "main" java.util.regex.PatternSyntaxException: Unexpected internal error near index 3
    \\Q\\E
       ^
    	at java.util.regex.Pattern.error(Unknown Source)
    	at java.util.regex.Pattern.compile(Unknown Source)
    	at java.util.regex.Pattern.<init>(Unknown Source)
    	at java.util.regex.Pattern.compile(Unknown Source)
    	at java.lang.String.replaceAll(Unknown Source)
    	at Work2$MetaFilenameFilter.<init>(Work2.java:67)
    Avec la ligne 67 qui correspond à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    regexpPattern = regexpPattern.replaceAll("\\\\Q\\\\E", "");
    J'execute avec java 6. Une idée sur le problème ?

  6. #6
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    292
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 292
    Points : 317
    Points
    317
    Par défaut
    retire \\
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    regexpPattern = regexpPattern.replaceAll("\\Q\\E", "");

  7. #7
    Membre régulier
    Homme Profil pro
    Inscrit en
    Février 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Février 2007
    Messages : 80
    Points : 76
    Points
    76
    Par défaut
    Merci jhaythem !

    Effectivement plus d'erreur à l'exécution du programme. Mais avec ce que tu proposes la routine ne supprime plus les \Q\E inutiles. Ce n'est pas un problème en soi j'ai l'impression... donc autant virer la ligne ?

    Par ailleurs je ne comprends pas bien ce qu'apporte l'ajout sytématique des balises \Q et \E ?
    Est-ce que le constructeur de MetaFileFilter (la classe proposée par adiGuba) peut s'écrire plus simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    // Transforme les points en charactère non regex
    String regexPattern = fileMask.replaceAll("\\.", "\\\\.");
    // Remplace les ? par l'équivalent regex
    regexPattern = regexPattern.replaceAll("\\?", "\\.");
    // Remplace les * par l'équivalent regex
    regexPattern = regexPattern.replaceAll("\\*", "\\.\\*\\?");
    pattern = Pattern.compile(regexPattern);
    A l'exécution ça à l'air de fonctionner pareil, mais ya peut-être qqch qui m'échappe. Et si adiGuba a codé comme ça, ya surement une bonne raison !

  8. #8
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    292
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 292
    Points : 317
    Points
    317
    Par défaut
    pour etre honete j ai meme pas lu ton code, j ai juste vu l erreur.

    Le probleme viens du mix des regex avec String, je viens de l'expliquer dans un autre post que j arrive plus a trouver
    String p = "." // le metacharacter "."
    String p= "\." // le compilateur voit ca comme un java escape illegal
    comme pour le \n et \b ...
    et en plus ca depend de la version de ta jvm c est pour ca que ca marchait pour
    adiGuba et pas pour toi.

  9. #9
    Membre régulier
    Homme Profil pro
    Inscrit en
    Février 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Février 2007
    Messages : 80
    Points : 76
    Points
    76
    Par défaut
    Merci pour vos réponses.
    J'en sais pas beaucoup plus sur les quantifiers ... mais bon, j'apprendrai en grandissant
    Philippe

  10. #10
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Points : 5 943
    Points
    5 943
    Par défaut
    Voici un constructeur de la classe MetaFilenameFilter qui devrait résoudre le problème (il faudrait tout de même le tester sur les JVM qui plante avec l'ancien code).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public MetaFilenameFilter(String fileMask) {
        // Ajout de \Q \E autour des sous-chaines de fileMask 
        // qui ne sont pas des meta-caractères :
        String regexpPattern = fileMask.replaceAll("[^\\*\\?]+", "\\\\Q$0\\\\E");
        // On remplace toutes les occurrences de '*' afin de les interpréter :
        regexpPattern = regexpPattern.replaceAll("\\*", ".*");
        // On remplace toutes les occurrences de '?' afin de les interpréter :
        regexpPattern = regexpPattern.replaceAll("\\?", ".");
        // On crée le pattern :
        this.pattern = Pattern.compile(regexpPattern);
    }
    Je ne répondrai à aucune question technique par MP.

    Pensez aux Tutoriels et aux FAQs avant de poster (pour le java il y a aussi JavaSearch), n'oubliez pas non plus la fonction Rechercher.
    Enfin, quand une solution a été trouvée à votre problème
    pensez au tag

    Cours Dvp : http://ydisanto.developpez.com
    Blog : http://yann-disanto.blogspot.com/
    Page perso : http://yann-disanto.fr

  11. #11
    Membre régulier
    Homme Profil pro
    Inscrit en
    Février 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Février 2007
    Messages : 80
    Points : 76
    Points
    76
    Par défaut
    Bonjour Le Yam's,

    Ok c'est très clair : tu "quote" toutes les sous-chaines qui ne contiennent ni ? ni * et tu transformes ces deux méta-charactères shell en leurs équivalents regex pour qu'ils soient interprétés, avant de compiler le pattern !
    Limpide et ça marche parfaitement avec la JVM 1.6.0

    Merci. A +

  12. #12
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Désolé de ne pas avoir participé plus tôt (les vacances vous savez ce que c'est )

    Citation Envoyé par pverley Voir le message
    Mais avec ce que tu proposes la routine ne supprime plus les \Q\E inutiles. Ce n'est pas un problème en soi j'ai l'impression... donc autant virer la ligne ?
    En effet la ligne posant problème n'est pas obligatoire mais sert simplement à supprimer des \Q\E inutile et ainsi à ne pas trop alourdir la regexp...
    On pouvait très bien se contenter de la supprimer sans que cela ne pose problème...

    Citation Envoyé par pverley Voir le message
    Par ailleurs je ne comprends pas bien ce qu'apporte l'ajout sytématique des balises \Q et \E ?
    L'ajout des des \Q\E permet simplement de ne pas interpréter les autres caractères... Les regexps utilisent un grand nombre de caractères spéciaux (ou de structures) qui sont interprétés si on ne les protèges pas. Il est bien trop complexe de protéger tous ces caractères un à un donc la solution passe par les \Q\E qui permettent de protéger toute une sous-chaine...

    Citation Envoyé par pverley Voir le message
    A l'exécution ça à l'air de fonctionner pareil, mais ya peut-être qqch qui m'échappe. Et si adiGuba a codé comme ça, ya surement une bonne raison !
    Cela fonctionne pareil avec des expressions simples, mais certains caractères pourraient poser problème car il serait interpréter en tant que regexp et non pas en tant que simple caractère...



    Pour en revenir au problème, il s'agit apparemment d'un bug de régression de Java 6 (bug_id=6497148), et la meilleure solution est donc d'utiliser la version de le y@m's.
    J'ai d'ailleurs mis à jours ma contribution aux codes sources afin de prendre en compte tout cela...




    a++

  13. #13
    Membre régulier
    Homme Profil pro
    Inscrit en
    Février 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Février 2007
    Messages : 80
    Points : 76
    Points
    76
    Par défaut
    Bonjour,

    Désolé de ne pas avoir participé plus tôt (les vacances vous savez ce que c'est )
    Pa ni probleme ! Merci beaucoup pour ces derniers éclaircissements.
    Et bon courage pour la reprise ...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Conseils architecture type LINUX
    Par azigui91 dans le forum RedHat / CentOS / Fedora
    Réponses: 3
    Dernier message: 10/12/2010, 17h03
  2. [generics] Génériques à types multiples
    Par sanchou dans le forum Langage
    Réponses: 6
    Dernier message: 06/07/2007, 09h42
  3. Spécifier type de système de fichiers sous linux
    Par rond24 dans le forum Administration système
    Réponses: 4
    Dernier message: 07/03/2006, 20h09
  4. comment gérer le type HANDLE sous linux?
    Par poune dans le forum Autres éditeurs
    Réponses: 2
    Dernier message: 11/06/2004, 11h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo