2013-06-03 155 views
14

我在一个文件夹中有一组文件,并且它们都以类似名称开头,除了一个。这里有一个例子:如何按升序对文件名进行排序?

Coordinate.txt 
Spectrum_1.txt 
Spectrum_2.txt 
Spectrum_3.txt 
. 
. 
. 
Spectrum_11235 

我能够从指定的文件夹列表中的所有文件,但列表不在谱号的升序排列。示例:执行程序时得到以下结果:

Spectrum_999.txt 
Spectrum_9990.txt 
Spectrum_9991.txt 
Spectrum_9992.txt 
Spectrum_9993.txt 
Spectrum_9994.txt 
Spectrum_9995.txt 
Spectrum_9996.txt 
Spectrum_9997.txt 
Spectrum_9998.txt 
Spectrum_9999.txt 

但是这个顺序是不正确的。 Spectrum_999.txt后应该有Spectrum_1000.txt文件。谁能帮忙?这里是代码:

import java.io.*; 
import java.util.Arrays; 
import java.util.Comparator; 
import java.util.Scanner; 

    public class FileInput { 

     public void userInput() 
     { 
      Scanner scanner = new Scanner(System.in); 
      System.out.println("Enter the file path: "); 
      String dirPath = scanner.nextLine(); // Takes the directory path as the user input 

      File folder = new File(dirPath); 
      if(folder.isDirectory()) 
      { 
       File[] fileList = folder.listFiles(); 

       Arrays.sort(fileList); 

       System.out.println("\nTotal number of items present in the directory: " + fileList.length); 


       // Lists only files since we have applied file filter 
       for(File file:fileList) 
       { 
        System.out.println(file.getName()); 
       } 

       // Creating a filter to return only files. 
       FileFilter fileFilter = new FileFilter() 
       { 
        @Override 
        public boolean accept(File file) { 
         return !file.isDirectory(); 
        } 
       }; 

       fileList = folder.listFiles(fileFilter); 

       // Sort files by name 
       Arrays.sort(fileList, new Comparator() 
       { 
        @Override 
        public int compare(Object f1, Object f2) { 
         return ((File) f1).getName().compareTo(((File) f2).getName()); 
        } 
       }); 

       //Prints the files in file name ascending order 
       for(File file:fileList) 
       { 
        System.out.println(file.getName()); 
       } 

      } 
     } 
    } 

回答

25

你所要求的是数值排序。您需要实施Comparator并将其传递给Arrays#sort方法。在比较方法中,您需要从每个文件名中提取数字,然后比较数字。

为什么你现在所得到的输出的原因是,排序发生alphanumerically

这里一个是做的一个非常基本的方式。该代码使用简单的String-操作来提取数字。如果你知道文件名的格式,这在你的情况下是Spectrum_<number>.txt。进行提取的更好方法是使用regular expression

public class FileNameNumericSort { 

    private final static File[] files = { 
     new File("Spectrum_1.txt"), 
     new File("Spectrum_14.txt"), 
     new File("Spectrum_2.txt"), 
     new File("Spectrum_7.txt"),  
     new File("Spectrum_1000.txt"), 
     new File("Spectrum_999.txt"), 
     new File("Spectrum_9990.txt"), 
     new File("Spectrum_9991.txt"), 
    }; 

    @Test 
    public void sortByNumber() { 
     Arrays.sort(files, new Comparator<File>() { 
      @Override 
      public int compare(File o1, File o2) { 
       int n1 = extractNumber(o1.getName()); 
       int n2 = extractNumber(o2.getName()); 
       return n1 - n2; 
      } 

      private int extractNumber(String name) { 
       int i = 0; 
       try { 
        int s = name.indexOf('_')+1; 
        int e = name.lastIndexOf('.'); 
        String number = name.substring(s, e); 
        i = Integer.parseInt(number); 
       } catch(Exception e) { 
        i = 0; // if filename does not match the format 
          // then default to 0 
       } 
       return i; 
      } 
     }); 

     for(File f : files) { 
      System.out.println(f.getName()); 
     } 
    } 
} 

输出

Spectrum_1.txt 
Spectrum_2.txt 
Spectrum_7.txt 
Spectrum_14.txt 
Spectrum_999.txt 
Spectrum_1000.txt 
Spectrum_9990.txt 
Spectrum_9991.txt 
+0

这是如何得到这么多upvotes?它无法正确地对问题中的输入列表进行排序,其中包括前缀不相同的文件,例如'Coordinate.txt' –

+0

@LukasEder'这是一个非常基本的做法。此代码使用简单的字符串操作来提取数字。如果你知道文件名的格式,在你的情况下Spectrum_ .txt。提取的一种更好的方法是使用正则表达式。“这里的答案并不意味着提供完全正常的生产质量代码,而不是提供有关如何解决问题的提示以及最终的基本代码示例。我希望我能回答你的问题。 – A4L

+0

*“这里的答案并不意味着提供完整的生产质量代码”* - 那么,这是一个方法。另一种情况是:根据OP的要求,这根本就是错误的,而且很容易得到正确的结果:-) –

-1

你可以使用Collections.sort(fileList);排序arraylist。

然后使用

for(File file:fileList)     
     System.out.println(file.getName()); 

Collections.sort()

+0

我试过了,但是对于 'Collections.sort(fileList);' 显示如下错误: '方法排序(表)在类型集合不适用于参数(文件[])' – novicegeek

+0

这有什么 – PSR

+0

我删除代码中的问题'Arrays.sort(的fileList,新的比较() \t \t \t { \t \t \t \t @覆盖 \t \t \t \t公众诠释比较(对象F1,目标F2){ \t \t \t \t \t回报((文件)F1).getName()的compareTo(((文件)F2).getName ()); \t \t \t \t} \t \t \t});',并试图'Collections.sort(的fileList);'但示出了以下错误:'在类型类别的方法的排序(列表)是不适用的参数(File [])'如何继续? – novicegeek

1
Arrays.sort(fileList, new Comparator() 
{ 
    @Override 
    public int compare(Object f1, Object f2) { 
     String fileName1 = ((File) f1).getName(); 
     String fileName2 = ((File) f1).getName(); 

     int fileId1 = Integer.parseInt(fileName1.split("_")[1]); 
     int fileId2 = Integer.parseInt(fileName2.split("_")[1]); 

     return fileId1 - fileId2; 
    } 
}); 

确保办理的名义

2

NameFileComparator类下议院IO库提供不具有文件_有功能排序文件数组按名称,最后修改日期,大小和更多。文件可以按升序和降序排序,大小写敏感或者不区分大小写。

导入:

org.apache.commons.io.comparator.NameFileComparator

代码:

File directory = new File("."); 
File[] files = directory.listFiles(); 
Arrays.sort(files, NameFileComparator.NAME_COMPARATOR) 
+1

这并不排序OP想要的方式。它忽略了数字。 – c4k

1

您可以找到解决方案,在上述评论你的问题,但考虑到只有链接已出版我给代码从该网站。工作很好。

  1. 您需要创建自己的AlphanumericalComparator。

    import java.io.File; 
    import java.util.Comparator; 
    
    public class AlphanumFileComparator implements Comparator 
    { 
    
        private final boolean isDigit(char ch) 
        { 
        return ch >= 48 && ch <= 57; 
        } 
    
    
    private final String getChunk(String s, int slength, int marker) 
    { 
        StringBuilder chunk = new StringBuilder(); 
        char c = s.charAt(marker); 
        chunk.append(c); 
        marker++; 
        if (isDigit(c)) 
        { 
         while (marker < slength) 
         { 
          c = s.charAt(marker); 
          if (!isDigit(c)) 
           break; 
          chunk.append(c); 
          marker++; 
         } 
        } else 
        { 
         while (marker < slength) 
         { 
          c = s.charAt(marker); 
          if (isDigit(c)) 
           break; 
          chunk.append(c); 
          marker++; 
         } 
        } 
        return chunk.toString(); 
    } 
    
    public int compare(Object o1, Object o2) 
    { 
        if (!(o1 instanceof File) || !(o2 instanceof File)) 
        { 
         return 0; 
        } 
        File f1 = (File)o1; 
        File f2 = (File)o2; 
        String s1 = f1.getName(); 
        String s2 = f2.getName(); 
    
        int thisMarker = 0; 
        int thatMarker = 0; 
        int s1Length = s1.length(); 
        int s2Length = s2.length(); 
    
        while (thisMarker < s1Length && thatMarker < s2Length) 
        { 
         String thisChunk = getChunk(s1, s1Length, thisMarker); 
         thisMarker += thisChunk.length(); 
    
         String thatChunk = getChunk(s2, s2Length, thatMarker); 
         thatMarker += thatChunk.length(); 
    
         /** If both chunks contain numeric characters, sort them numerically **/ 
    
         int result = 0; 
         if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) 
         { 
          // Simple chunk comparison by length. 
          int thisChunkLength = thisChunk.length(); 
          result = thisChunkLength - thatChunk.length(); 
          // If equal, the first different number counts 
          if (result == 0) 
          { 
           for (int i = 0; i < thisChunkLength; i++) 
           { 
            result = thisChunk.charAt(i) - thatChunk.charAt(i); 
            if (result != 0) 
            { 
             return result; 
            } 
           } 
          } 
         } else 
         { 
          result = thisChunk.compareTo(thatChunk); 
         } 
    
         if (result != 0) 
          return result; 
        } 
    
        return s1Length - s2Length; 
    } 
    } 
    

2.对文件进行排序,这取决于这个类。

 File[] listOfFiles = rootFolder.listFiles(); 
    Arrays.sort(listOfFiles, new AlphanumFileComparator()); 
    ...to sth with your files. 

希望它有帮助。它对我来说就像魅力一样。

解决方案来自:http://www.davekoelle.com/files/AlphanumComparator.javahere

-1

只是另一种方式来做到这一点,但使用java8的功率

List<Path> x = Files.list(Paths.get("C:\\myPath\\Tools")) 
      .filter(p -> Files.exists(p)) 
      .map(s -> s.getFileName()) 
      .sorted() 
      .collect(Collectors.toList()); 

x.forEach(System.out::println); 
+0

如果您使用映射,排序和后面的所有内容将被提供文件名(= String对象)而不是实际的路径或文件对象。在收集结果时,'toList'实际上会生成一个'List '而不是'List '对象。我已经调整你的代码,以满足我的需求:'File [] sortedFiles = Arrays.stream(files).filter(f - > Files.exists(f.toPath()))。sorted(Comparator.comparing(File: :getName))。toArray(File [] :: new);' –

1

currently accepted answer做到这一点只对文件的数字后缀,即总是叫同一个名字(即忽略前缀)。

A much more generic solution, which I blogged about here,可与任何文件名一起使用,按分段名称拆分名称,并按数字顺序(如果两个分段都是数字)或按字典顺序排列,否则。 Idea inspired from this answer

public final class FilenameComparator implements Comparator<String> { 
    private static final Pattern NUMBERS = 
     Pattern.compile("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)"); 
    @Override public final int compare(String o1, String o2) { 
     // Optional "NULLS LAST" semantics: 
     if (o1 == null || o2 == null) 
      return o1 == null ? o2 == null ? 0 : -1 : 1; 

     // Splitting both input strings by the above patterns 
     String[] split1 = NUMBERS.split(o1); 
     String[] split2 = NUMBERS.split(o2); 
     for (int i = 0; i < Math.min(split1.length, split2.length); i++) { 
      char c1 = split1[i].charAt(0); 
      char c2 = split2[i].charAt(0); 
      int cmp = 0; 

      // If both segments start with a digit, sort them numerically using 
      // BigInteger to stay safe 
      if (c1 >= '0' && c1 <= '9' && c2 >= 0 && c2 <= '9') 
       cmp = new BigInteger(split1[i]).compareTo(new BigInteger(split2[i])); 

      // If we haven't sorted numerically before, or if numeric sorting yielded 
      // equality (e.g 007 and 7) then sort lexicographically 
      if (cmp == 0) 
       cmp = split1[i].compareTo(split2[i]); 

      // Abort once some prefix has unequal ordering 
      if (cmp != 0) 
       return cmp; 
     } 

     // If we reach this, then both strings have equally ordered prefixes, but 
     // maybe one string is longer than the other (i.e. has more segments) 
     return split1.length - split2.length; 
    } 
} 

这也可以处理具有破坏版本的版本,例如,之类的东西version-1.2.3.txt

+0

我看你正在使用正则表达式,我想知道你从哪里得到灵感...我想你应该得到一个cookie ;-) – A4L

+0

@ A4L:对,我已经记下了我的来源,因为我应该有! –

+0

我希望我可以给你另一个饼干:) – A4L

1

只需使用:

  1. 对于升序:Collections.sort(名单)

  2. 对于降序:Collections.sort(名单,Collections.reverseOrder())

+0

**它必须的类型_List _ ** –

相关问题