2

Hello I'm trying to get with numerical order all files that exist in a folder.

First i check a folder(main folder) the sub-folders that contained in. After that, for each sub-folder I'm getting the names of the files that exist in.
I wrote a code that does this job for me but when i print (the names of the files of a sub-folder) I'm not getting them with the correct order.(numerical).

For example i have my main Folder called 'test', in there exist 3 sub-folder named Sub1, Sub2, Sub3

 FOLDER Test *contains* [  FOLDER SUB1   || FOLDER SUB2  ||  FOLDER SUB3 ]

Each sub-Fodler have files with names (1.txt , 2.txt ,.....,15.txt,16.txt,...,22.txt,...etc)

This code does this job... but...

import java.io.File;
import java.io.FileFilter;
public class Main {
public static void main(String[] args) {
    File file = new File("C:\\test");
    File[] files = file.listFiles(new FileFilter() {
        public boolean accept(File f) {       
            String name=f.getName(); //read every subfodler name
            System.out.println(name);        
            File folder = new File("C:\\test\\"+name); //for each subfolder
            File[] listOfFiles = folder.listFiles();  
            for (int i = 0; i < listOfFiles.length; i++) {
                if (listOfFiles[i].isFile()) {
                    System.out.println("File " + listOfFiles[i].getName());
                    //print the names of files that included
                } else if (listOfFiles[i].isDirectory()) {
                    System.out.println("Directory " + listOfFiles[i].getName());      
                }    
            } 
            return f.isDirectory();
        }});   
    }   
}

but the output is like that...

 Folder1               
 File 1.txt
 File 10.txt
 File 11.txt
 File 12.txt
 File 13.txt
 File 14.txt
 File 2.txt
 File 3.txt
 File 4.txt
 File 5.txt
 File 6.txt
 File 7.txt
 File 8.txt
 File 9.txt
 Folder2
 ............... same order as Folder1 ... etc

How i could taking the file names with numerical order so the output that i will get will be like that:

 Folder1               
 File 1.txt
 File 2.txt
 File 3.txt
 File 4.txt
 File 5.txt
 File 6.txt
 File 7.txt
 File 8.txt
 File 9.txt
 File 10.txt
 File 11.txt
 File 12.txt
 File 13.txt
 File 14.txt
Arun Sudhakaran
  • 2,167
  • 4
  • 27
  • 52
Nakos Kotsanis
  • 180
  • 1
  • 15
  • 1
    They already are in ascending order. What you want is *numerical* order – BackSlash Dec 25 '17 at 18:03
  • 1
    https://stackoverflow.com/questions/203030/best-way-to-list-files-in-java-sorted-by-date-modified- possible sol – Cruzer Dec 25 '17 at 18:05
  • More people will look at your code if you indent it properly. Right now, it’s pretty hard to read. Also, you are misusing FileFilter; its job is only to filter files, and it should not be used as a “for each file” shortcut. – VGR Dec 26 '17 at 00:51

2 Answers2

0

Once you have the files in a list or array you can sort them using Collections.sort() or Arrays.sort() and a custom comparator like in this example

sam46
  • 1,273
  • 9
  • 12
  • 1
    This gives a hint to the solution, but is not a complete answer. Also, no need for an ArrayList; just use [Arrays.sort](https://docs.oracle.com/javase/9/docs/api/java/util/Arrays.html#sort-T:A-java.util.Comparator-). – VGR Dec 26 '17 at 00:47
  • It is a hint. and oops thought he was storing the files in a list – sam46 Dec 26 '17 at 04:37
0

java.io.File is an obsolete class. It was replaced years ago by Path and other classes in the java.nio.file package, like Files and Paths.

You should not use a filter to perform any actions other than filtering. Yes, it works, but you’re relying on side effects instead of the intended functionality.

For comparing the numeric part of a filename, you will need to write your own Comparator:

Path root = Paths.get("C:\\test");

Pattern numericFileNamePattern = Pattern.compile(".*[^0-9]([0-9]+)\\.[^.]+");

Comparator<Path> byNumber = (p1, p2) -> {

    String name1 = p1.getFileName().toString();
    String name2 = p2.getFileName().toString();

    Matcher matcher = numericFileNamePattern.matcher(name1);
    if (matcher.matches()) {

        String digits1 = matcher.group(1);
        String withoutDigits1 = matcher.replaceFirst("");

        matcher.reset(name2);
        if (matcher.matches()) {

            String digits2 = matcher.group(1);
            String withoutDigits2 = matcher.replaceFirst("");

            if (withoutDigits1.equals(withoutDigits2)) {
                long num1 = Long.parseLong(digits1);
                long num2 = Long.parseLong(digits2);

                return Long.compare(num1, num2);
            }
        }
    }

    return p1.compareTo(p2);
};

try (DirectoryStream<Path> dir = Files.newDirectoryStream(root)) {
    for (Path child : dir) {
        if (Files.isDirectory(child)) {

            try (Stream<Path> listing = Files.list(child)) {
                Path[] files = listing.filter(f -> Files.isRegularFile(f))
                    .sorted(byNumber).toArray(Path[]::new);

                for (Path file : files) {
                    System.out.println(file);
                }
            }

        }
    }
}
VGR
  • 40,506
  • 4
  • 48
  • 63
  • https://docs.oracle.com/javase/9/docs/api/java/io/File.html is not obsolete, just because Path can do more. It's still not deprecated and part of the JDK. – Robert Dec 26 '17 at 17:28
  • @Robert Like Vector, Hashtable, and Enumeration, it is used by too many other classes to deprecate. The File class has no value beyond interoperation with other APIs. – VGR Dec 26 '17 at 17:32