Home > Software design >  how to output sorted files in java
how to output sorted files in java

Time:09-12

I have a problem where I want to scan the files that are in a certain folder and output them. the only problem is that the output is: (1.jpg , 10.jpg , 11.jpg , 12.jpg , ... , 19.jpg , 2.jpg) when I want it to be: (1.jpg , 2.jpg and so on). Since I use: File actual = new File(i.); (i is the number of times the loop repeats) to scan for images, I don't know how to sort the output.

this is my code for now.

//variables
        String htmlHeader = ("<!DOCTYPE html>:\n"
                  "<html lang=\"en\">\n"
                  "<head>\n"
                  "<meta charset=\"UTF-8\">\n"
                  "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n"
                  "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
                  "<title>Document</title>\n"
                  "</head>"
                  "<body>;\n");
        String mangaName = ("THREE DAYS OF HAPPINESS");
        String htmlEnd = ("</body>\n</html>");
        String image = ("image-");

//ask for page number
        Scanner scan = new Scanner(System.in);
        System.out.print("enter a chapter number: ");
        int n = scan.nextInt();


//create file for chapter
        File creator = new File("manga.html");

//for loop
        for (int i = 1; i <= n;   i) {

//writing to HTML file
        BufferedWriter bw = null;
        bw = new BufferedWriter(new FileWriter("manga" i ".html"));
        bw.write(htmlHeader);
        bw.write("<h2><center>"   mangaName   "</center></h2</br>");

//scaning files                
        File actual = new File("Three Days Of Happiness Chapter " i " - Manganelo_files.");
        for (File f : actual.listFiles()) {
            String pageName = f.getName();

//create list
            List<String> list = Arrays.asList(pageName);
             list.sort(Comparator.nullsFirst(Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder())));  
             System.out.println("list");
    //for loop
//writing bpdy to html file
           
bw.write("<p><center><img src=\"Three Days Of Happiness Chapter " i " - Manganelo_files/"   pageName   "\" <br/></p>\n");
                
            System.out.println(pageName);
        }
        bw.write(htmlEnd);
        bw.close();
        System.out.println("Process Finished");
    }}
}```

CodePudding user response:

When you try to sort the names, you'll most certainly notice that they are sorted alphanumerically (e.g. Comparing 9 with 12; 12 would come before 9 because the leftmost digit 1 < 9).

One way to get around this is to use an extended numbering format when naming & storing your files.

This has been working great for me when sorting pictures, for example. I use YYYY-MM-DD for all dates regardless whether the day contains one digit (e.g. 9) or two digits (11). This would mean that I always type 9 as 09. This also means that every file name in a given folder has the same length, and each digit (when compared to the corresponding digit to any other adjacent file) is compared properly.

One solution to your problem is to do the same and add zeros to the left of the file names so that they are easily sorted both by the OS and by your Java program. The drawback to this solution is that you'll need to decide the maximum number of files you'll want to store in a given folder beforehand – by setting the number of digits properly (e.g. 3 digits would mean a maximum of 1000 uniquely & linearly numbered file names from 000 to 999). The plus, however, is that this will save you the hassle of having to sort unevenly numerered files, while making it so that your files are pre-sorted once and are ready to be quickly read whenever.

CodePudding user response:

Generally, file systems do not have an order to the files in a directory. Instead, anything that lists files (be it an ls or dir command on a command line, calling Files.list in java code, or opening Finder or Explorer) will apply a sorting order.

One common sorting order is 'alphanumerically'. In which case, the order you describe is correct: 2 comes after 1 and also after 10. You can't wave a magic wand and tell the OS or file system driver not to do that; files as a rule don't have an 'ordering' property.

Instead, make your filenames such that they do sort the way you want, when sorting alphanumerically. Thus, the right name for the first file would be 01.jpg. Or possibly even 0001.jpg - you're going to have to make a call about how many digits you're going to use before you start, unfortunately.

String.format("d", 1) becomes "00001" - that's pretty useful here.

The same principle applies to reading files - you can't just rely on the OS sorting it for you. Instead, read it all into e.g. a list of some sort and then sort that. You're going to have to write a fairly funky sorting order: Find the dot, strip off the left side, check if it is a number, etc. Quite complicated. It would be a lot simpler if the 'input' is already properly zero-prefixed, then you can just sort them naturally instead of having to write a complex comparator.

That comparator should probably by modal. Comparators work by being handed 2 elements, and you must say which one is 'earlier', and you must be consistent (if a is before b, and later I ask you: SO, how about b and a, you must indicate that b is after a).

Thus, an algorithm would look something like:

  • Determine if a is numeric or not (find the dot, parseInt the substring from start to the dot).
  • Determine if b is numeric or not.
  • If both are numeric, check ordering of these numbers. If they have an order (i.e. aren't identical), return an answer. Otherwise, compare the stuff after the dot (1.jpg should presumably be sorted before 1.png).
  • If neither are numeric, just compare alphanum (aName.compareTo(bName)).
  • If one is numeric and the other one is not, the numeric one always wins, and vice versa.
  • Related