2010-06-18 5 views
11

J'ai un programme Java simple qui lit un répertoire de fichiers et affiche une liste de fichiers. Je trier les fichiers par nom:Trier les fichiers par nom en Java diffère de Windows Explorer

String [] files = dirlist.list(); 
files = sort(files); 

Mon problème est que ce trie par nom d'une autre manière que ne l'Explorateur Windows. Par exemple si j'ai les fichiers suivants: abc1.doc, abc12.doc, abc2.doc.

Java triera comme ceci:

abc1.doc 
abc12.doc 
abc2.doc 

Quand j'ouvre le dossier dans l'Explorateur Windows, les fichiers sont triés comme ceci:

abc1.doc 
abc2.doc 
abc12.doc 

Comment puis-je faire Java trier mes fichiers comme dans Windows Explorer? Est-ce un truc de Windows?

+2

Voir http://stackoverflow.com/questions/442429/windows-explorer-sort-method –

Répondre

18

Windows Explorer utilise son propre algorithme. Pour trier vos fichiers comme Explorer ne, vous devez créer un comparateur personnalisé pour faire l'affaire:

public class WindowsExplorerStringComparator implements Comparator<String> 
    { 
     private String str1, str2; 
     private int pos1, pos2, len1, len2; 

     public int compare(String s1, String s2) 
     { 
     str1 = s1; 
     str2 = s2; 
     len1 = str1.length(); 
     len2 = str2.length(); 
     pos1 = pos2 = 0; 

     int result = 0; 
     while (result == 0 && pos1 < len1 && pos2 < len2) 
     { 
      char ch1 = str1.charAt(pos1); 
      char ch2 = str2.charAt(pos2); 

      if (Character.isDigit(ch1)) 
      { 
      result = Character.isDigit(ch2) ? compareNumbers() : -1; 
      } 
      else if (Character.isLetter(ch1)) 
      { 
      result = Character.isLetter(ch2) ? compareOther(true) : 1; 
      } 
      else 
      { 
      result = Character.isDigit(ch2) ? 1 
        : Character.isLetter(ch2) ? -1 
        : compareOther(false); 
      } 

      pos1++; 
      pos2++; 
     } 

     return result == 0 ? len1 - len2 : result; 
     } 

     private int compareNumbers() 
     { 
     int end1 = pos1 + 1; 
     while (end1 < len1 && Character.isDigit(str1.charAt(end1))) 
     { 
      end1++; 
     } 
     int fullLen1 = end1 - pos1; 
     while (pos1 < end1 && str1.charAt(pos1) == '0') 
     { 
      pos1++; 
     } 

     int end2 = pos2 + 1; 
     while (end2 < len2 && Character.isDigit(str2.charAt(end2))) 
     { 
      end2++; 
     } 
     int fullLen2 = end2 - pos2; 
     while (pos2 < end2 && str2.charAt(pos2) == '0') 
     { 
      pos2++; 
     } 

     int delta = (end1 - pos1) - (end2 - pos2); 
     if (delta != 0) 
     { 
      return delta; 
     } 

     while (pos1 < end1 && pos2 < end2) 
     { 
      delta = str1.charAt(pos1++) - str2.charAt(pos2++); 
      if (delta != 0) 
      { 
      return delta; 
      } 
     } 

     pos1--; 
     pos2--; 

     return fullLen2 - fullLen1; 
     } 

     private int compareOther(boolean isLetters) 
     { 
     char ch1 = str1.charAt(pos1); 
     char ch2 = str2.charAt(pos2); 

     if (ch1 == ch2) 
     { 
      return 0; 
     } 

     if (isLetters) 
     { 
      ch1 = Character.toUpperCase(ch1); 
      ch2 = Character.toUpperCase(ch2); 
      if (ch1 != ch2) 
      { 
      ch1 = Character.toLowerCase(ch1); 
      ch2 = Character.toLowerCase(ch2); 
      } 
     } 

     return ch1 - ch2; 
     } 
    } 

Maintenant, l'utiliser comme ceci:

Arrays.sort(files, new WindowsExplorerStringComparator()); 
+1

Merci! ça marche :) –

+0

Je voulais ajouter que: l'argument nommé "files" doit être de type String [] – kiltek

0

Trier par chaîne puis par la longueur du nom.

3

Cela ressemble à cela.

Cependant, vous pouvez utiliser Arrays.sort() et fournir un Comparator personnalisé pour qu'il fonctionne comme Windows Explorer.

0

Ceci est un autre essayer de le mettre en œuvre en Java:

Java - Sort Strings like Windows Explorer

En bref, il divise les deux chaînes à comparer dans la lettre - Pièces de chiffres et compare ces pièces d'une manière spécifique pour réaliser ce genre de tri.

Avec ceci son IMHO un peu plus lisible.

Questions connexes