Ignore:
Timestamp:
2004-03-26T15:26:24+12:00 (20 years ago)
Author:
mdewsnip
Message:

A much improved method for sorting file nodes into alphabetical order, with directories coming first. The old version was very very slow on Windows 95 and 98 computers with a large number of files (>3000) in the directory; this version is still slow, but a great deal better than before.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gli/src/org/greenstone/gatherer/util/ArrayTools.java

    r6770 r7121  
    408408    }
    409409
    410     /** Sorts an array of files. */
    411     static public void sort(File[] files) {
    412     sort(files, false);
    413     }
    414 
    415     /** Sorts an array of files. Can also to instructed to list directories first. Case insensitive.
    416      * @param files The File[] to be sorted.
    417      * @param directories_first true if you want to directories to be listed first.
    418      */
    419     static public void sort(File[] files, boolean directories_first) {
    420     if(files != null && files.length > 1) {
    421         FileComparator comparator = new FileComparator(directories_first);
    422         Arrays.sort(files, comparator);
    423     }         
    424     }
     410
     411    /** Sorts an array of files, putting non-files first. Case insensitive.
     412     * @param files_to_sort The File[] to be sorted.
     413     */
     414    static public void sort(File[] files_to_sort)
     415    {
     416    // Return if there is nothing to sort
     417    if (files_to_sort == null || files_to_sort.length <= 1) {
     418        return;
     419    }
     420
     421    FileSystemView fileSystemView = FileSystemView.getFileSystemView();
     422    FileComparator comparator = new FileComparator();
     423
     424    // Separate the file system roots and directories from the files, and sort separately
     425    ArrayList files_list = new ArrayList((files_to_sort.length * 3) / 4);
     426    ArrayList non_files_list = new ArrayList((files_to_sort.length) / 4);
     427    for (int i = 0; i < files_to_sort.length; i++) {
     428        File file = files_to_sort[i];
     429
     430        // File is a system root
     431        if (fileSystemView.isFileSystemRoot(file)) {
     432        non_files_list.add(file);
     433        }
     434        // File is a directory
     435        else if (file.isDirectory()) {
     436        non_files_list.add(file);
     437        }
     438        // File is an actual file
     439        else {
     440        files_list.add(file);
     441        }
     442    }
     443    System.err.println("Number of files: " + files_list.size());
     444    System.err.println("Number of non-files: " + non_files_list.size());
     445
     446    Object[] files = files_list.toArray();
     447    Object[] non_files = non_files_list.toArray();
     448
     449    // Sort files
     450    Arrays.sort(files, comparator);
     451
     452    // Sort non-files
     453    Arrays.sort(non_files, comparator);
     454
     455    // Merge the results, putting non-files before files
     456    int j = 0;
     457    for (int i = 0; i < non_files.length; i++) {
     458        files_to_sort[j++] = (File) non_files[i];
     459    }
     460    for (int i = 0; i < files.length; i++) {
     461        files_to_sort[j++] = (File) files[i];
     462    }
     463    }
     464
    425465
    426466    /** Comparator used to order files. */
    427467    static private class FileComparator
    428468    implements Comparator {
    429     private boolean directories_first = false;
    430 
    431     public FileComparator(boolean directories_first) {
    432         this.directories_first = directories_first;
    433     }
     469
    434470    /** Compare two files in terms of ordering of their paths.
    435471     * @param o1 The <strong>Object</strong> that represents the first file.
    436472     * @param o2 The other <strong>Object</strong>, also a file.
    437      * @return An <i>int</i> which is <1, 0 or >1 if o1 is < o2, = o2 or > o2 respectively.
     473     * @return An <i>int</i> which is <1, 0 or >1 if o1 is <o2, =o2 or >o2 respectively.
    438474     */
    439     public int compare(Object o1, Object o2) {
    440         int result = 0;
     475    public int compare(Object o1, Object o2)
     476    {
    441477        File f1 = (File) o1;
    442         String n1 = f1.getName().toLowerCase();
    443478        File f2 = (File) o2;
    444         String n2 = f2.getName().toLowerCase();
    445                 // Special checks for system roots as these include removable media drives and thus we should never attempt to call isDirectory until the user explicitly attempts to map drive.
    446         boolean f1_system_root = FileSystemView.getFileSystemView().isFileSystemRoot(f1);
    447         boolean f2_system_root = FileSystemView.getFileSystemView().isFileSystemRoot(f2);
    448         if((f1_system_root && f2_system_root) || (!f2_system_root && f1_system_root && f2.isDirectory()) || (!f1_system_root && f1.isDirectory() && f2_system_root) || (f1.isDirectory() && f2.isDirectory()) || (f1.isFile() && f2.isFile())) {
    449         result = n1.compareTo(n2);
    450         }
    451         else if(f1_system_root || f1.isDirectory()) {
    452         result = -1;
    453         }
    454         else {
    455         result = 1;
    456         }
    457         return result;
    458     }
    459     /** Compare two files for equality, in terms of their file paths.
    460      * @param obj The <strong>Object</strong> representing the file we are about to compare ourselves to.
    461      * @return <i>true</i> if we equal the given file, <i>false</i> otherwise.
    462      */
    463     public boolean equals(Object obj) {
    464         return (compare(this, obj) == 0);
     479
     480        return f1.getName().compareToIgnoreCase(f2.getName());
    465481    }
    466482    }
Note: See TracChangeset for help on using the changeset viewer.