I have a set of files in a folder, and all of them starting with a similar name, except one. Here is an example:
Coordinate.txt Spectrum_1.txt Spectrum_2.txt Spectrum_3.txt . . . Spectrum_11235
I am able to list all the files from the specified folder, but the list is not in an ascending order of the spectrum number. Example: I get the following result when the program is executed:
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
But this order is not correct. There should be Spectrum_1000.txt file after Spectrum_999.txt. Can anyone help? Here is the code:
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()); } } } }
Advertisement
Answer
What you are asking for is numerical sort. You need implement a Comparator and pass it to the Arrays#sort method. In the compare method you need to extract the number from each filename an then compare the numbers.
The reason why you get the output you are getting now is that sorting happens alphanumerically
Here a is a very basic way of doing it. This code uses simple String
-operation to extract the numbers. This works if you know the format of the filename, in your case Spectrum_<number>.txt
. A better way of doing the extraction is to use 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()); } } }
Output
Spectrum_1.txt Spectrum_2.txt Spectrum_7.txt Spectrum_14.txt Spectrum_999.txt Spectrum_1000.txt Spectrum_9990.txt Spectrum_9991.txt