Sort files "numerically" instead of alphabet in java

I have a folder with files whose names appear after timestamps.

When I try to go through each file, it sorts them alphabetically and gives me this order:

/home/user/buffereddata/1 /home/user/buffereddata/100 /home/user/buffereddata/1000 /home/user/buffereddata/200 /home/user/buffereddata/2000 /home/user/buffereddata/300 

But I want them to be sorted as follows:

 /home/user/buffereddata/1 /home/user/buffereddata/100 /home/user/buffereddata/200 /home/user/buffereddata/300 /home/user/buffereddata/1000 /home/user/buffereddata/2000 

This is my code:

 File file = new File(System.getProperty("user.home") + "/buffereddata"); if(file.exists()) { File[] fileArray = file.listFiles(); Arrays.sort(fileArray); for(File f : fileArray) { System.out.println(f); } } 

Is there any (preferably simple) way to cycle files around in such a way that I want to skip them?

+4
source share
4 answers
 Arrays.sort(fileArray, new Comparator<File>() { public int compare(File f1, File f2) { try { int i1 = Integer.parseInt(f1.getName()); int i2 = Integer.parseInt(f2.getName()); return i1 - i2; } catch(NumberFormatException e) { throw new AssertionError(e); } } }); 
+10
source

you need a custom comparator

  Arrays.sort(fileArray, new Comparator<File>() { public int compare(File f1, File f2) { int n1 = Integer.parseInt(f1.getName()); int n2 = Integer.parseInt(f1.getName()); return Integer.compare(n1, n2); }}); 
+3
source

While the other answers are correct in your particular case (where all the file names in this directory are only numeric), here you can find a solution that can compare mixed numeric / non-numeric file names, for example. version-1.10.3.txt an intuitive way, similar to how Windows Explorer does it:

enter image description here

The idea ( which I wrote about here . The idea was inspired by this answer here .) Is to split the file name into numerical / non-numerical segments, and then compare each individual segment from two file names either numerically (if both are numerical) , or alpha number otherwise:

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

Then you can use the comparator as such:

 Arrays.sort(fileArray, Comparators.comparing(File::getName, new FilenameComparator())); 
0
source

Based on this answer :

You can define your own comparator with a comparison function as:

 public class FileSizeComparator implements Comparator<File> { public int compare( File a, File b ) { String aName = a.getName(); String bName = b.getName(); // make both strings equal size by padding 0s to the smaller one // then compare the strings return aName.compareTo(bName); // dictionary order! } } 

compareTo is a method of the String class that works to your advantage here.

 "0100".compareTo("1000"); // < 0 "0100".compareTo("0200"); // < 0 "0200".compareTo("1000"); // < 0 

So, if you have 100, 200, 1000, you get 100, 200, 1000, and not 100, 1000, 200!

Should work, not tested!

-1
source

Source: https://habr.com/ru/post/1488455/


All Articles