-4

I've got a method that returns to me a String[] of names of the Files of a current path, the thing I'm trying to do is make a method that returns to me this String[] of names but sorted by date, and sorted by size, I've almost done this, but I'm missing something. I know to sort it's used Arrays.sort() but the thing is that I don't know how to join all.

This is what I've got (No sorted)

 File dir = new File(this.path);
 File[] filelist = dir.listFiles();
 String[] theNamesOfFiles;
 if (filelist.length == 0) {
     theNamesOfFiles = new String[1];
 } else {
     theNamesOfFiles = new String[filelist.length];
 }

 if (filelist.length == 0) {
     theNamesOfFiles[0] = "This folder is empty";
 } else {
     for (int i = 0; i < theNamesOfFiles.length; i++) {

         theNamesOfFiles[i] = filelist[i].getName();
     }
 }
 return theNamesOfFiles;

Now I tried to do a SortByDate() method but I don't know how to make to get those File[] to make the previous method :

 public File[] SortByDate(File test) {
 final File[] sortedByDate = test.listFiles();
 if (sortedByDate != null && sortedByDate.length > 1) {
     Arrays.sort(sortedByDate, new Comparator < File > () {
         @Override
         public int compare(File object1, File object2) {
             return (int)((object1.lastModified() > object2.lastModified()) ? object1.lastModified() : object2.lastModified());
         }
     });
     return sortedByDate;
 }
 return sortedByDate;
 }

And I think I know how to get the size of a File doing :

Integer.parseInt(String.valueOf(filelist[i].length() / 1024))

Shall I do this also with the Compare<File>()?

What I'm misunderstanding or missing?

EDIT

Now what I've tried is create a private File[] SortedByDate;, and I've implemented this method :

public void SortByDate() {

File test = new File(this.path);
this.SortedByDate = test.listFiles();

if (this.SortedByDate != null && this.SortedByDate.length > 1) {
    Arrays.sort(this.SortedByDate, new Comparator < File > () {
        @Override
        public int compare(File object1, File object2) {
            return (int)((object1.lastModified() > object2.lastModified()) ? object1.lastModified() : object2.lastModified());
        }
    });
}
for (int i = 0; i < this.SortedByDate.length; i++) {
    Log.d("SortedByDate", this.SortedByDate[i].getName());
}
}

And then I've created another method that looks like :

public String[] FilesFoundSortedByDate() {
SortByDate();
String[] theNamesOfFiles;
if (this.SortedByDate.length == 0) {
    theNamesOfFiles = new String[1];
} else {
    theNamesOfFiles = new String[this.SortedByDate.length];
}

if (this.SortedByDate.length == 0) {
    theNamesOfFiles[0] = "This folder is empty";
} else {
    for (int i = 0; i < theNamesOfFiles.length; i++) {

        theNamesOfFiles[i] = this.SortedByDate[i].getName();
    }
}
return theNamesOfFiles;
}

And I thought to call the function of SortByDate and then use the File[] of the new attribute created, but it isn't sorting.

user489041
  • 27,916
  • 55
  • 135
  • 204
Skizo-ozᴉʞS ツ
  • 19,464
  • 18
  • 81
  • 148

6 Answers6

3

Sorting functions. Modify them as needed. All they are doing is make use of values and compareTo() method calls. The key to understanding this is available here.

String logic together as needed to form your function for your sort as it is slightly confusing on what the actual sort requirements need to be.

 private void sortByName(File[] files){
     Arrays.sort(files, new Comparator<File>() {
        @Override
        public int compare(File t, File t1) {
            return t.getName().compareTo(t1.getName());
        }
    });
}

private void sortByDate(File[] files){
    Arrays.sort(files, new Comparator<File>() {
        @Override
        public int compare(File t, File t1) {
            return (int) (t.lastModified() - t1.lastModified());
        }
    });
}

private void sortBySize(File[] files){
     Arrays.sort(files, new Comparator<File>() {
        @Override
        public int compare(File t, File t1) {
            return (int) (t.length() - t1.length());
        }
    });
}
user489041
  • 27,916
  • 55
  • 135
  • 204
1

Sort file list by date ascending and size ascending.

 void SortByDateAndSize(File[] fileList) {
    Arrays.sort(fileList, new Comparator<File>() {
        @Override
        public int compare(File o1, File o2) {
            int r = Long.compare(o1.lastModified(), o2.lastModified());
            if (r != 0)
                return r;
            return Long.compare(o1.length(), o2.length());
        }
    });
}
1

I used the Java 8 Stream and Lamda features, to create a function which sorts the files in a directory by the last modified time and the file size.

public static String[] getSortedFileNames(File directory) {
    return Arrays
        // get all the files from the directory
        .stream(directory.listFiles())
        // sorting them first by last modified time and then by length
        // the sorted function uses a comparator (like your Comparator<File>
        // or a function which compares two files
        .sorted((f1, f2) -> {
            // first compare the two files by last modified (newest files first => compare f2 with f1)
            final int compareModified = Long.compare(f2.lastModified(), f1.lastModified());
            return compareModified != 0 
                ? compareModified 
                : Long.compare(f2.length(), f1.length()); // the two files have the same last modified time,
                                                          // lets sort them by file size (biggest files first)
        })
        // get the name of the file
        .map(File::getName)
        // return the names from the sorted files in a String array
        .toArray(String[]::new);
}

Updated using Files.list(path) (the updated method now can throw an IOException):

public static String[] sortFiles(File directory) throws IOException {
    return Files
        // get all the paths in the directory
        .list(directory.toPath())
        // turn paths into files
        .map(Path::toFile)
        // sortying them first by last modfied and then by length
        .sorted((f1, f2) -> {
            // the sorted function uses a comparotor or a function which compares two files
            // first compare the two files by last modified (newest files first => * -1)
            final int compareModified = Long.compare(f2.lastModified(), f1.lastModified());
            return compareModified != 0 
                ? compareModified 
                : Long.compare(f2.length(), f1.length()); // the two files have the same last modified time,
                                                          // lets sort them by file size (biggist first)
        })
        // get the name of the file
        .map(File::getName)
        // return the names from the sorted files in a String array
        .toArray(String[]::new);
}

Update 2 using only the nio file API.

Comparing Paths using Files.getLastModifiedTime and Files.size. I have to throw a RuntimeException when one of these methods throws an IOException because it is not possible to throw a (checked) exception from a lambda in a stream (which also would not be possible in the compare method of a Comparator<Path>).

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

// run : sortFiles(Paths.get("/foo/bar/"))
public static String[] sortFiles(Path directory) throws IOException {
    return Files
        .list(directory)
        .sorted((p1, p2) -> {
            try {
                final int compareModified = Files.getLastModifiedTime(p2).compareTo(Files.getLastModifiedTime(p1));
                return compareModified != 0
                    ? compareModified
                    : Long.compare(Files.size(p2), Files.size(p1));
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        })
        .map(Path::getFileName)
        .map(Path::toString)
        .toArray(String[]::new);
}
Community
  • 1
  • 1
Peter Neyens
  • 9,770
  • 27
  • 33
  • @Peter Nice code, but have your read the JavaDoc of File.listFiles()? There is mentioned that one better take a Files.newDirectoryStream for large scale directories for performance issues. – aw-think Jun 18 '15 at 02:03
  • @NwDX Thank you for the tip. I found [`Files.list(path)`](http://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#list-java.nio.file.Path-) which uses a `DirectoryStream` underneath. – Peter Neyens Jun 18 '15 at 07:01
  • @PeterNeyens Hm, your update code do a Path.toFile(), so there may be the next drawback. I thougt of a code more like this, without old io-package (except for IOException): `stream.sorted(timeSizeComparator).map(Path::getFileName).map(Path::toString).toArray(String[]::new);` – aw-think Jun 18 '15 at 14:15
  • @NwDx Thank you. I already knew going back from `Path`s to `File`s was not the right approach, but I am not yet that familiar with the nio API. I have updated my answer to only use `nio`, but the nio functions possibly throw an `IOException`, which does not play nice with Streams and Comparators. – Peter Neyens Jun 18 '15 at 15:12
  • @PeterNeyens Yes, streams and exceptions are a bit tricky. I've made a solution on this question too. But to be honest, I have to thank you for pushing me the right way :-) So, hopefully this will be the "fastest" solution with nio features. – aw-think Jun 18 '15 at 15:21
1

I threw together a little demo with lambdas

public static void main(String[] args) {

    File f = new File(System.getProperty("user.home") + "/temp");

    List<File> files = Arrays.asList(f.listFiles(((dir, name) -> !(new File(dir,name)).isDirectory())));

    System.out.println("****** Listing as received *********** ");
    files.forEach(file -> System.out.println(file.getName()));

    System.out.println("****** Listing sorted by length *********** ");
    files.sort((f1,f2) -> Long.compare(f1.length(),f2.length()));
    files.forEach(file -> System.out.println(
          String.format("%-30s length = %2d",file.getName(),file.length())));

    System.out.println("****** Listing sorted by date **************");
    files.sort((f1,f2) -> Long.compare(f1.lastModified(),f2.lastModified()));
    files.stream()
          .map(file -> String.format("%-30s date mod = %2$td-%2tm-%2$tY %2$tH:%2$tM:%2$ts",file.getName(), new Date(file.lastModified())))
          .collect(Collectors.toList()).forEach(System.out::println);
}

The generated output

****** Listing as received *********** 
.DS_Store
allclasses-frame.html
allclasses-noframe.html
alltext_awesome.test
alltext_java8.test
alltext_oldjava.text
bigDbTesting.mv.db
bigDbTesting.trace.db
constant-values.html
cx_d_entity_npn.txt
default-centos-66-pmd1.box
deprecated-list.html
F_TXN_Refresh.SFS.kjb
fakedata.mv.db
faker.mv.db
help-doc.html
index.html
jdk160_26.zip
keepPass_v0.xml
ldapinfo.txt
overview-frame.html
overview-summary.html
overview-tree.html
package-list
script.js
simpleDbToFileTest.txt
simpleDbToFileTest2.txt
stringIncrementer.jar
stylesheet.css
table.csv
temp.sql
those.enc.copy.properties
those.enc.properties
those.properties
untitled text 4.txt
untitled text.txt
untitled text111.txt
****** Listing sorted by length *********** 
cx_d_entity_npn.txt            length =  0
package-list                   length = 20
untitled text 4.txt            length = 39
untitled text111.txt           length = 132
simpleDbToFileTest.txt         length = 180
ldapinfo.txt                   length = 295
untitled text.txt              length = 695
script.js                      length = 827
overview-frame.html            length = 850
those.enc.copy.properties      length = 853
those.enc.properties           length = 853
allclasses-noframe.html        length = 1243
allclasses-frame.html          length = 1343
temp.sql                       length = 1504
those.properties               length = 1836
bigDbTesting.trace.db          length = 2673
index.html                     length = 2863
simpleDbToFileTest2.txt        length = 3201
deprecated-list.html           length = 3514
constant-values.html           length = 3564
overview-summary.html          length = 4043
alltext_awesome.test           length = 4546
alltext_java8.test             length = 4546
alltext_oldjava.text           length = 4546
overview-tree.html             length = 4821
F_TXN_Refresh.SFS.kjb          length = 7254
help-doc.html                  length = 8242
stringIncrementer.jar          length = 12243
.DS_Store                      length = 12292
stylesheet.css                 length = 12808
keepPass_v0.xml                length = 14810
faker.mv.db                    length = 28672
table.csv                      length = 47820
bigDbTesting.mv.db             length = 212992
fakedata.mv.db                 length = 75051008
jdk160_26.zip                  length = 87253361
default-centos-66-pmd1.box     length = 20131307999
****** Listing sorted by date **************
jdk160_26.zip                  date mod = 04-04-2014 10:09:1396620572
simpleDbToFileTest2.txt        date mod = 02-07-2014 14:07:1404324435
simpleDbToFileTest.txt         date mod = 03-07-2014 08:05:1404389127
cx_d_entity_npn.txt            date mod = 23-09-2014 15:39:1411501165
F_TXN_Refresh.SFS.kjb          date mod = 23-09-2014 16:17:1411503474
keepPass_v0.xml                date mod = 21-10-2014 16:48:1413924527
ldapinfo.txt                   date mod = 22-10-2014 10:39:1413988799
untitled text111.txt           date mod = 08-12-2014 09:05:1418047503
default-centos-66-pmd1.box     date mod = 03-02-2015 10:56:1422978975
untitled text 4.txt            date mod = 06-02-2015 23:14:1423282475
untitled text.txt              date mod = 06-02-2015 23:14:1423282475
stringIncrementer.jar          date mod = 13-02-2015 18:19:1423869592
fakedata.mv.db                 date mod = 19-02-2015 08:31:1424352716
faker.mv.db                    date mod = 24-03-2015 14:49:1427222991
table.csv                      date mod = 30-04-2015 10:07:1430402823
bigDbTesting.mv.db             date mod = 30-04-2015 10:33:1430404409
bigDbTesting.trace.db          date mod = 30-04-2015 10:43:1430405015
.DS_Store                      date mod = 27-05-2015 09:28:1432733304
alltext_awesome.test           date mod = 08-06-2015 08:51:1433767887
alltext_java8.test             date mod = 08-06-2015 08:51:1433767887
alltext_oldjava.text           date mod = 08-06-2015 08:51:1433767887
stylesheet.css                 date mod = 08-06-2015 10:24:1433773446
package-list                   date mod = 08-06-2015 10:25:1433773522
script.js                      date mod = 08-06-2015 10:25:1433773522
overview-frame.html            date mod = 08-06-2015 10:25:1433773522
allclasses-noframe.html        date mod = 08-06-2015 10:25:1433773522
allclasses-frame.html          date mod = 08-06-2015 10:25:1433773522
index.html                     date mod = 08-06-2015 10:25:1433773522
deprecated-list.html           date mod = 08-06-2015 10:25:1433773522
constant-values.html           date mod = 08-06-2015 10:25:1433773522
overview-summary.html          date mod = 08-06-2015 10:25:1433773522
overview-tree.html             date mod = 08-06-2015 10:25:1433773522
help-doc.html                  date mod = 08-06-2015 10:25:1433773522
temp.sql                       date mod = 08-06-2015 15:21:1433791297
those.properties               date mod = 11-06-2015 14:33:1434047622
those.enc.copy.properties      date mod = 11-06-2015 15:38:1434051531
those.enc.properties           date mod = 11-06-2015 15:49:1434052178
MadConan
  • 3,749
  • 1
  • 16
  • 27
1

Easiest way is :

import org.apache.commons.io
import java.util.Arrays;

then

File directory = new File(".");
File[] files = directory.listFiles((FileFilter) FileFileFilter.FILE);
Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE);

other comparators available in that library:

CompositeFileComparator, DefaultFileComparator, DirectoryFileComparator, ExtensionFileComparator, NameFileComparator, PathFileComparator, SizeFileComparator.

Charles Mosndup
  • 600
  • 6
  • 19
0

Even this post already has an absolutly correct answer, I've tried to do all things without old Java IO Package things, using only NIO features for performance issues. So here it is (sorts descending). I don't know if it is available in Android, but in Java 8 it is. (Based on things from Peter Neyens solution). This solution is based on an other question from me Why does the java DirectoryStream perform so slow?

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FileSorter2 {

  public String[] getSortedFileList(Path dir) throws IOException {
    return Files.list(dir).map(PathInfo::new).sorted().map(p -> p.
            getFileName()).toArray(String[]::new);
  }

  public static void main(String[] args) throws IOException {
    // some testing, this main throws IOException
    Path dir = Paths.get("C:\\Windows\\system32");

    FileSorter2 fs = new FileSorter2();
    long before = System.currentTimeMillis();
    String[] sortedFileNames = fs.getSortedFileList(dir);
    long after = System.currentTimeMillis();
    System.out.println("Time needed: " + (after - before));

  }

  // Helping class to cache object which is compared
  static class PathInfo implements Comparable<PathInfo> {

    private final String fileName;
    private final long modified;
    private final long size;

    public PathInfo(Path path) {
      try {
        fileName = path.getFileName().toString();
        modified = Files.getLastModifiedTime(path).toMillis();
        size = Files.size(path);
      } catch (IOException ex) {
        throw new UncheckedIOException(ex);
      }
    }

    @Override
    public int compareTo(PathInfo o) {
      int cmp = Long.compare(modified, o.modified);
      if (cmp == 0) {
        cmp = Long.compare(size, o.size);
      }
      return cmp;
    }

    public String getFileName() {
      return fileName;
    }
  }
}
Community
  • 1
  • 1
aw-think
  • 4,723
  • 2
  • 21
  • 42