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

Langage Java Discussion :

trier par nom une liste de fichier


Sujet :

Langage Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 176
    Par défaut trier par nom une liste de fichier
    Bonjour,

    Je travaille sur un programme java qui a une partie qui consiste à lister les fichiers d'un répertoire et des les afficher par nom (comme sous windows).
    Seulement toutes les méthodes que j'ai utilisé pour le moment ne fonctionnent pas comme je le veux.

    En clair:
    Dans mon répertoire, il y a ces fichiers :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    1.xml
    2.xml
    ...
    10.xml
    11.xml
    ...
    100.xml
    Ceci est l'affichage windows.

    et lorsque je suis avec java, il me liste les fichiers de la manière suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    1.xml
    10.xml
    100.xml
    ...
    11.xml
    110.xml
    ...
    2.xml
    20.xml
    ...
    et cela n'est pas ça que je veux.

    Est-ce que vous pouvez m'aider, s'il vous plait?
    Je suis presque sur que d'autre on eu déjà ce problème mais je n'arrive pas à trouver sur le net la solution.

    Merci d'avance,

    Pierre

  2. #2
    Membre éclairé Avatar de biozaxx
    Profil pro
    Inscrit en
    Août 2004
    Messages
    403
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 403
    Par défaut
    salut

    c'est parceque tu fais un tri alphanumerique sur le nom de tes fichiers or si tes fichiers on pour prefixe uniquement des chiffres, il faut que tu fasses un tri numerique sur le nom de tes fichiers (en virant le .xml)

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 277
    Par défaut
    Va voir la classe Collections et les méthodes sort.
    Si la méthode sort de base ne te satisfait pas, utilise celle avec un comparateur en paramètre.

  4. #4
    Membre chevronné Avatar de T`lash
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Saint-Pierre-Et-Miq.

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Septembre 2007
    Messages : 381
    Par défaut
    Demande manuellement le tri par nom dans l'explorer Windows et il y a de toutes les chances que tu vois l'ordre changer.
    Là il les trie par ordre chronologique de génération.
    Windows aussi place 2 après 10 et 100.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 176
    Par défaut
    Citation Envoyé par biozaxx Voir le message
    salut

    c'est parceque tu fais un tri alphanumerique sur le nom de tes fichiers or si tes fichiers on pour prefixe uniquement des chiffres, il faut que tu fasses un tri numerique sur le nom de tes fichiers (en virant le .xml)
    En fait j'ai mis pour exemple avec des chiffres seulement mais je peux avoir des prefix devant les chiffres.

    par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    toto1.xml
    toto2.xml
    ...
    Citation Envoyé par T`lash Voir le message
    Demande manuellement le tri par nom dans l'explorer Windows et il y a de toutes les chances que tu vois l'ordre changer.
    Là il les trie par ordre chronologique de génération.
    Windows aussi place 2 après 10 et 100.
    J'ai essayé et windows trie bien comme je l'ai expliqué plus haut quand je fais un tri par nom et il ne place pas 10 et 100 avant 2.

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    Crée donc ton propre java.util.Comparator<?> qui permet de décider dans quel ordre trier tes chaînes de caractères. (comme fr1man l'a dit, au passage)

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 176
    Par défaut
    Citation Envoyé par dingoth Voir le message
    Crée donc ton propre java.util.Comparator<?> qui permet de décider dans quel ordre trier tes chaînes de caractères. (comme fr1man l'a dit, au passage)
    J'ai essayé de le faire en définissant mon propre comparateur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public class FileNameComparator implements Comparator{
     
        public int compare(Object o1, Object o2) {
            String S1 = (String) o1;
            String S2 = (String) o2;
            return S2.compareTo(S1);
        }
    }
    Seulement le comparateur de String, compare les chaines suivants l'ordre lexicographique. En clair, c'est celui par défaut lorsque l'on liste les fichiers d'un répertoire.

    En clair, il faudrait que je fasse mon propre comparateur de chaine de caractères. Là je suis tout à fait d'accord avec vous. Cependant j'ai deux raisons pour essayer de chercher une autre solution et de solliciter votre aide:

    La première ce que si c'est l'ordre de tri par nom de l'explorateur de windows c'est que quelqu'un (même plusieurs personnes) l'a déjà fait.

    La deuxième est que si quelqu'un l'a déjà fait, il aura surement fait quelque chose de plus optimisé que moi.


    Une petite question au passage, pour faire ce comparateur de String, est-ce que vous avez une idée qui soit mieux que celle que j'ai qui consiste a comparer mes chaines caractère par caractère?

    Merci d'avance,

    Pierre

  8. #8
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    À ta raison 1, je réponds oui, mais pas forcément en java. Sinon, y'a toujours google pour t'en assurer.

    À ta raison 2, bah... elle dépend du 1

    Mais bon, le code, le voici (en Java5+) :
    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
    public class NameFileComparator implements Comparator<File>{
      public int compare(File file1, File file2) {
        String s1 = file1.getName();
        String s2 = file2.getName();
        int i1 = 0;
        int i2 = 0;
        Character c1, c2;
        int len = Math.min(s1.length(),s2.length());
        while (i1 <s1.length() && i2 < s2.length()) {
          c1 = s1.charAt(i1);
          c2 = s2.charAt(i2);
          if (Character.isDigit(c1) && Character.isDigit(c2)) {
            int len1 = 1;
            while (i1+len1 < s1.length() && Character.isDigit(s1.charAt(i1+len1))) {
              len1++;
            }
            int len2 = 1;
            while (i2+len2 < s2.length() && Character.isDigit(s2.charAt(i2+len2))) {
              len2++;
            }
            String num1 = s1.substring(i1,len1);
            String num2 = s2.substring(i2,len2);
            int c = Integer.parseInt(num1) - Integer.parseInt(num2);
            if (c != 0)
              return c;
            if (!num1.equals(num2)) {
              return num1.compareTo(num2);
            }
            i1 += len1;
            i2 += len2;
          } else {
            int c = c1.compareTo(c2);
            // Si File001.xml == file001.xml, décommenter la ligne suivante et commenter la précédente
            // int c = c1.toUpperCase().compareTo(c2.toUpperCase());
            if (c != 0)
              return c;
            i1++;
            i2++;
          }
        }
        return (s1.length()-i1) - (s2.length()-i2);
      }
    }
    Et si c'est pas ça, la solution doit pas être bien loin.

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 132
    Par défaut
    Sinon ce petit comparator devrait résoudre ton problème non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Collections.sort(orderedFiles, new Comparator<File> (){
     
                @Override
                public int compare(File o1, File o2) {
                    int diff = o1.getName().length()-o2.getName().length();
     
                    return (diff == 0 ? o1.getName().compareTo(o2.getName()) : diff);
                }
                }
     
            });
    Par exemple voici mon testcase:
    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
     HashSet<File> files = new HashSet <File> ();
            for (int i=1;i<50;i++){
                files.add (new File (i+".xml"));
            }
     
            ArrayList<File> orderedFiles = new ArrayList<File> (files);
     
            System.out.println ("unordered files:");
            for (File fileName:orderedFiles){
                System.out.println (fileName.getName());
            }
     
            Collections.sort(orderedFiles, new Comparator<File> (){
     
                           @Override
                public int compare(File o1, File o2) {
                    int diff = o1.getName().length()-o2.getName().length();
     
                    return (diff == 0 ? o1.getName().compareTo(o2.getName()) : diff);
                }
     
            });
     
            System.out.println ("Ordered files:");
            for (File fileName:orderedFiles){
                System.out.println (fileName.getName());
            }
    et le resultat:
    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
     
    unordered files:
    13.xml
    24.xml
    16.xml
    5.xml
    37.xml
    43.xml
    8.xml
    29.xml
    25.xml
    22.xml
    48.xml
    6.xml
    18.xml
    19.xml
    46.xml
    23.xml
    40.xml
    31.xml
    21.xml
    44.xml
    12.xml
    26.xml
    38.xml
    4.xml
    17.xml
    11.xml
    34.xml
    30.xml
    39.xml
    47.xml
    45.xml
    1.xml
    15.xml
    20.xml
    36.xml
    41.xml
    14.xml
    33.xml
    10.xml
    28.xml
    32.xml
    9.xml
    42.xml
    3.xml
    35.xml
    49.xml
    2.xml
    7.xml
    27.xml
    Ordered files:
    1.xml
    2.xml
    3.xml
    4.xml
    5.xml
    6.xml
    7.xml
    8.xml
    9.xml
    10.xml
    11.xml
    12.xml
    13.xml
    14.xml
    15.xml
    16.xml
    17.xml
    18.xml
    19.xml
    20.xml
    21.xml
    22.xml
    23.xml
    24.xml
    25.xml
    26.xml
    27.xml
    28.xml
    29.xml
    30.xml
    31.xml
    32.xml
    33.xml
    34.xml
    35.xml
    36.xml
    37.xml
    38.xml
    39.xml
    40.xml
    41.xml
    42.xml
    43.xml
    44.xml
    45.xml
    46.xml
    47.xml
    48.xml
    49.xml

  10. #10
    Membre chevronné Avatar de T`lash
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Saint-Pierre-Et-Miq.

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Septembre 2007
    Messages : 381
    Par défaut
    elmor, ta méthode est la plus simple, mais c'est aussi la plus appropriée....

    Autant réutiliser ce qui marche et corriger ce qui ne fonctionne pas.

    C'est à dire dans le premier cas lorsque les chaines sont de même longueur et dans le second lorsque les longueurs diffèrent.

  11. #11
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    Ok. Et si je crée 0001.xml et 10.xml ? Ou même aaaa01.xml et zz01.xml.

    Là, j'aimerais quand même dans les deux cas que le premier soit avant le second. Pas vous ?

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 176
    Par défaut
    Citation Envoyé par dingoth Voir le message
    Ok. Et si je crée 0001.xml et 10.xml ? Ou même aaaa01.xml et zz01.xml.

    Là, j'aimerais quand même dans les deux cas que le premier soit avant le second. Pas vous ?
    Je suis d'accord avec toi.

    Merci beaucoup les gars.

    Pierre

  13. #13
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    Ma méthode le permet. Reprend-la donc Elle est plus longue, mais elle le permet comme il faut.

  14. #14
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    voici la version finale avec plusieurs cas rencontré : nombre, préfixe+nombre-pas-paddé, préfixe+nombre-paddé, différents-préfixe (voir le test-case.

    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    import java.io.File;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.HashSet;
     
    public class FileNameWithNumberComparator
    		implements Comparator<File> {
    	public int compare(File file1, File file2) {
    		String fileName1 = file1.getName();
    		String fileName2 = file2.getName();
     
    		int i1 = 0;
    		int i2 = 0;
    		Character c1, c2;
    		String sub1, sub2;
    		while (i1 < fileName1.length() && i2 < fileName2.length()) {
    			c1 = fileName1.charAt(i1);
    			c2 = fileName2.charAt(i2);
    			if (Character.isDigit(c1) && Character.isDigit(c2)) {
    				sub1 = readNumber(fileName1, i1);
    				sub2 = readNumber(fileName2, i2);
    				int c = Integer.parseInt(sub1) - Integer.parseInt(sub2);
    				if (c != 0)
    					return c;
    				if (!sub1.equals(sub2)) {
    					return sub1.compareTo(sub2);
    				}
    				i1 += sub1.length();
    				i2 += sub2.length();
    			} else {
    				int c = c1.compareTo(c2);
    				// Si File001.xml == file001.xml, décommenter la ligne suivante
    				// et commenter la précédente
    				// int c = c1.toUpperCase().compareTo(c2.toUpperCase());
    				if (c != 0)
    					return c;
    				i1++;
    				i2++;
    			}
    		}
    		return (fileName1.length() - i1) - (fileName2.length() - i2);
    	}
     
    	private static String readNumber(String fileName, int offset) {
    		for (int i = offset + 1; i < fileName.length(); i++) {
    			if (!Character.isDigit(fileName.charAt(i))) {
    				return fileName.substring(offset, i);
    			}
    		}
    		return fileName.substring(offset);
    	}
     
    	public static void main(String... args) {
    		HashSet<File> files = new HashSet<File>();
    		for (int i = 1; i < 50; i++) {
    			files.add(new File(i + ".xml"));
    		}
     
    		for (int i = 1; i < 50; i++) {
    			files.add(new File("toto"+(i < 10 ? "0" : "") + i+".xml"));
    		}
     
    		for (int i = 1; i < 50; i++) {
    			files.add(new File("tata"+i+".xml"));
    		}
     
    		for (int i = 1; i < 50; i++) {
    			files.add(new File("toto0"+(i < 10 ? "0" : "") + i+".xml"));
    		}
     
     
    		ArrayList<File> orderedFiles = new ArrayList<File>(files);
     
    		System.out.println("unordered files:");
    		for (File fileName : orderedFiles) {
    			System.out.println(fileName.getName());
    		}
     
    		Collections.sort(orderedFiles, new FileNameWithNumberComparator());
     
    		System.out.println("Ordered files:");
    		for (File fileName : orderedFiles) {
    			System.out.println(fileName.getName());
    		}
    	}
    }

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 176
    Par défaut
    Bonjour,

    J'allais posté pour corriger une toute petite erreur dans l'algo précédent mais avant j'ai testé le dernier qui a été posté et l'erreur est corrigé.

    Merci énormément.

    Pierre

Discussions similaires

  1. [XL-2007] Modifier les noms d'une liste de fichier
    Par thomasmbai dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 29/08/2013, 01h33
  2. Aide [C++] Logiciel traitant le nom d'une liste de fichiers
    Par Sound4Lyon dans le forum Mon programme
    Réponses: 0
    Dernier message: 12/11/2008, 00h43
  3. Réponses: 5
    Dernier message: 03/01/2008, 17h07
  4. Réponses: 28
    Dernier message: 24/05/2006, 19h20
  5. [JSP] Trier par date une liste de fichier en JSP
    Par Total dans le forum Servlets/JSP
    Réponses: 10
    Dernier message: 21/02/2006, 16h38

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