如何按升序对文件名进行排序?

我在一个文件夹中有一组文件,所有文件都以类似的名字开头,除了一个。 这是一个例子:

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()); } } } } 

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

你得到你现在得到的输出的原因是排序发生在字母数字上

这是一个非常基本的方法。 此代码使用简单的String -operation来提取数字。 如果您知道文件名的格式(在您的情况下为Spectrum_.txt 。 更好的提取方法是使用正则表达式 。

 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() { @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 

当前接受的答案仅对始终称为相同名称的文件的数字后缀(即忽略前缀)执行此操作。

我在这里写博客的更通用的解决方案适用于任何文件名,分段中的名称和以数字方式(如果两个段都是数字)或按字典顺序排序段。 想法源于这个答案 :

 public final class FilenameComparator implements Comparator { 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 (eg 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 (ie has more segments) return split1.length - split2.length; } } 

这也可以处理带有颠覆的版本,例如version-1.2.3.txt

Commons IO库中提供的NameFileComparator类,具有按名称,最后修改日期,大小等排序文件数组的function。文件可以按升序和降序排序,区分大小写或不区分大小写。

import:

org.apache.commons.io.comparator.NameFileComparator

代码:

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

您可以在上面的评论中找到您的问题的解决方案,但考虑到只发布了链接,我正在从该网站提供代码。 工作得很好。

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

 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; } }); 

确保处理名称中没有_的文件

只需使用:

  1. 对于升序:Collections.sort(列表)

  2. 对于Descending:Collections.sort(List,Collections.reverseOrder())

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

然后用

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

Collections.sort()

只是另一种方式,但使用java8的力量

 List 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);