Array sorting of file paths

I am creating an array from a directory of images using listFiles() and then sorting them like so.

  images = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().toLowerCase().endsWith(".png");
            }
        });
   
   Arrays.sort(images);

However, the images in my directory don’t use leading zeros so look like this.

images/16/0.png
images/16/1.png
images/16/2.png

images/16/100.png
images/16/101.png

As I pull each one out in order I get 0.png, 1.png, 100.png etc. - not what I want, I want 0.png, 1.png, 2.png etc. Is there something that can be used in sort to resolve this or an alternative way of sorting that will correct this?

Back up your images

Write a processing code to rename the files in the folder

Sorry, I can’t run your code.

Can you post our entire code?

What imports do you use please?

This is a common problem that has no library solution I’ve ever encountered. I’ve always seen it solved by writing a custom sort function that parses the numbers out of the file names and uses them to determine the order.

2 Likes

You can also use one of the many free utility tools that let you rename files in batch.
You could easily add leading zeros to your number and use classic array sort to sort your files.

4 Likes

My approach to this would be to first order each String image filepath by length and then by its natural order. So, first you have all images/16/1.png … to images/16/9.png and so on.
In java 8 or above this could be accomplished using:

Arrays.sort(images,Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()));

But I don’t know with which version of java you are working on. If it is below 8 then you have to do a customized function but the logic might be the same

Hope it helps!

1 Like

Using Java 11 in Processing 4 so your comparator solution is the same one I’ve hit on. Your version here won’t work for me as is because you are using a String[] and I’m using a File[], which I didn’t specify, so it chokes on String::length. I thought something like str(File)::length but no - unclear how to pull out each file and convert is to a string so I can use length.

For everyone else telling me to rename files, this isn’t an option for me. I won’t be in control of the folder being traversed but apart from that leading zeros is not a great solution as it sets a count upper limit for the file name i.e. they have to stop at say 9999.png etc.

import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

String imagespath;
File[] images;

void setup()
{
  size(480, 672);

  // Path to images folder
  imagespath = sketchPath() + "/images/";
  File dir = new File(imagespath);

  // Get an array of all folders inside images folder
  File[] folders = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory();
            }
        });

  // Randomly select a folder
  int folderlength = folders.length;
  int i = int(random(folderlength));
  dir = new File(folders[i].getAbsolutePath() + "/");

  // Get an array of all png images
  images = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().toLowerCase().endsWith(".png");
            }
        });
   
   //Arrays.sort(images);
   //print(Arrays.toString(images) + "\n\n"); 

Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()));
print(Arrays.toString(images)); 
   exit();
}

Hi @garrettlynch

According to Oracle java documentation, File has a toString() method, which returns the pathname string of this abstract pathname. Maybe you need to invoke this method instead of str(). I tried running your code but since I don’t have the structure or images I can’t test it.
Hope it helps!

Check also these links:

Links

java - How to sort file names in ascending order? - Stack Overflow
NameFileComparator (Apache Commons IO 2.11.0 API)

If I have the time I will try to create random images to test your code again. But I highly doubt that this is something that cannot be solved with all Java IO File and NIO classes.

Just test the code snippet below after getting the images File[]

String arr[] = new String[images.length];
   for(int j = 0; j<images.length; j++){
     arr[j] = images[j].toString();
   }
 //  printArray(arr);

Arrays.sort(arr, Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder())));
printArray(arr); 
   
1 Like

Yes the natural sorting works (minus the extra typo bracket at the end of Arrays.sort()). I’m looking into the toString() method you mentioned in File. Would be nice/tidier to keep it as a File[] and just use the strings temporarily while sorting but failing that this will be my fall back solution. Many thanks for your help!