أفضل طريقة قائمة الملفات في جاوة ، مرتبة حسب تاريخ التعديل?

StackOverflow https://stackoverflow.com/questions/203030

  •  03-07-2019
  •  | 
  •  

سؤال

أريد الحصول على قائمة من الملفات في الدليل ، ولكن أريد أن نوع مثل أن أقدم الملفات أولا.الحل هو استدعاء الملف.listFiles و منتجع القائمة ملف.lastModified ، ولكن أنا أتساءل عما إذا كان هناك طريقة أفضل.

تحرير:بلدي الحل الحالي ، كما اقترح استخدام مجهول المقارنة:

File[] files = directory.listFiles();

Arrays.sort(files, new Comparator<File>(){
    public int compare(File f1, File f2)
    {
        return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());
    } });
هل كانت مفيدة؟

المحلول

وأعتقد أن الحل هو السبيل الوحيد المعقول. الطريقة الوحيدة للحصول على قائمة الملفات هو استخدام <لأ href = "http://java.sun.com/javase/6/docs/api/java/io/File.html#listFiles ()" يختلط = " noreferrer "> File.listFiles () وثائق تنص على أن هذا لا تقدم أي ضمانات حول ترتيب الملفات التي تم إرجاعها. ولذلك تحتاج لكتابة المقارنة أن الاستخدامات File.lastModified () ويمر هذا، جنبا إلى جنب مع مجموعة من الملفات، ل<لأ href = "http://java.sun.com/javase/6/docs/api/java/util/Arrays.html#sort(T[]،٪ 20java.util.Comparator) "يختلط =" noreferrer "> Arrays.sort () .

نصائح أخرى

وهذا قد يكون أسرع إذا كان لديك العديد من الملفات. يستخدم هذا النمط تزيين-نوع-undecorate ذلك أن آخر موعد المعدلة من كل ملف يتم جلب فقط <م> مرة واحدة بدلا من كل مرة خوارزمية الفرز يقارن الملفين. هذا يحتمل أن يقلل من عدد من I / O يدعو من O (ن سجل ن) إلى O (ن).

وانها رمز أكثر، ورغم ذلك وينبغي أن يستخدم فقط إذا كنت قلقا بشكل رئيسي مع السرعة وهو ملموس أسرع في الممارسة العملية (التي أشرت غير محددة).

class Pair implements Comparable {
    public long t;
    public File f;

    public Pair(File file) {
        f = file;
        t = file.lastModified();
    }

    public int compareTo(Object o) {
        long u = ((Pair) o).t;
        return t < u ? -1 : t == u ? 0 : 1;
    }
};

// Obtain the array of (file, timestamp) pairs.
File[] files = directory.listFiles();
Pair[] pairs = new Pair[files.length];
for (int i = 0; i < files.length; i++)
    pairs[i] = new Pair(files[i]);

// Sort them by timestamp.
Arrays.sort(pairs);

// Take the sorted pairs and extract only the file part, discarding the timestamp.
for (int i = 0; i < files.length; i++)
    files[i] = pairs[i].f;

وماذا عن نهج مماثل، ولكن من دون الملاكمة إلى كائنات طويلة:

File[] files = directory.listFiles();

Arrays.sort(files, new Comparator<File>() {
    public int compare(File f1, File f2) {
        return Long.compare(f1.lastModified(), f2.lastModified());
    }
});

أنيقة الحل منذ جافا 8:

File[] files = directory.listFiles();
Arrays.sort(files, Comparator.comparingLong(File::lastModified));

أو إذا كنت ترغب في ترتيب تنازلي ، فقط عكس ذلك:

File[] files = directory.listFiles();
Arrays.sort(files, Comparator.comparingLong(File::lastModified).reversed());

وكنت قد ننظر أيضا في اباتشي العموم IO ، فقد بنيت في <لأ href = " http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/comparator/LastModifiedFileComparator.html "يختلط =" noreferrer "> التعديل الأخير مقارنة و العديد من المرافق الأخرى لطيف للعمل مع الملفات.

في جاوة 8:

وArrays.sort(files, (a, b) -> Long.compare(a.lastModified(), b.lastModified()));

والواردات:

org.apache.commons.io.comparator.LastModifiedFileComparator

<وأ href = "http://commons.apache.org/proper/commons-io/javadocs/api-release/index.html؟org/apache/commons/io/comparator/package-summary.html" يختلط = "noreferrer"> أباتشي العموم

والرمز:

public static void main(String[] args) throws IOException {
        File directory = new File(".");
        // get just files, not directories
        File[] files = directory.listFiles((FileFilter) FileFileFilter.FILE);

        System.out.println("Default order");
        displayFiles(files);

        Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
        System.out.println("\nLast Modified Ascending Order (LASTMODIFIED_COMPARATOR)");
        displayFiles(files);

        Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
        System.out.println("\nLast Modified Descending Order (LASTMODIFIED_REVERSE)");
        displayFiles(files);

    }

إذا الملفات التي يتم الفرز يمكن تعديلها أو تحديثها في الوقت نفسه يتم تنفيذ هذا النوع:


جافا 8 +

private static List<Path> listFilesOldestFirst(final String directoryPath) throws IOException {
    try (final Stream<Path> fileStream = Files.list(Paths.get(directoryPath))) {
        return fileStream
            .map(Path::toFile)
            .collect(Collectors.toMap(Function.identity(), File::lastModified))
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByValue())
//            .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))  // replace the previous line with this line if you would prefer files listed newest first
            .map(Map.Entry::getKey)
            .map(File::toPath)  // remove this line if you would rather work with a List<File> instead of List<Path>
            .collect(Collectors.toList());
    }
}

جافا 7

private static List<File> listFilesOldestFirst(final String directoryPath) throws IOException {
    final List<File> files = Arrays.asList(new File(directoryPath).listFiles());
    final Map<File, Long> constantLastModifiedTimes = new HashMap<File,Long>();
    for (final File f : files) {
        constantLastModifiedTimes.put(f, f.lastModified());
    }
    Collections.sort(files, new Comparator<File>() {
        @Override
        public int compare(final File f1, final File f2) {
            return constantLastModifiedTimes.get(f1).compareTo(constantLastModifiedTimes.get(f2));
        }
    });
    return files;
}

و
كل من هذه الحلول إنشاء بنية بيانات الخريطة مؤقت لإنقاذ قبالة ثابت وقت آخر تعديل لكل ملف في الدليل. السبب في أننا بحاجة إلى القيام بذلك هو أنه إذا كان يتم تحديث الملفات أو تعديلها بينما يتم تنفيذ الفرز الخاص بك، ثم المقارنة الخاصة بك وسوف تنتهك شرط transitivity من العقد العام واجهة المقارنة لأن العصر آخر تعديل قد تتغير خلال المقارنة.

إذا، من ناحية أخرى، كما تعلمون لن يتم تحديث الملفات أو تعديلها أثناء الفرز، يمكنك الابتعاد الى حد كبير مع أي إجابة أخرى قدمت إلى هذه المسألة.

public String[] getDirectoryList(String path) {
    String[] dirListing = null;
    File dir = new File(path);
    dirListing = dir.list();

    Arrays.sort(dirListing, 0, dirListing.length);
    return dirListing;
}

يمكنك محاولة الجوافة يأمر:

Function<File, Long> getLastModified = new Function<File, Long>() {
    public Long apply(File file) {
        return file.lastModified();
    }
};

List<File> orderedFiles = Ordering.natural().onResultOf(getLastModified).
                          sortedCopy(files);

ويمكنك استخدام أباتشي <لأ href = "http://commons.apache.org/proper/commons-io/javadocs/api-1.4/org/apache/commons/io/comparator/LastModifiedFileComparator.html" يختلط = "نوفولو"> مكتبة LastModifiedFileComparator

 import org.apache.commons.io.comparator.LastModifiedFileComparator;  


File[] files = directory.listFiles();
        Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
        for (File file : files) {
            Date lastMod = new Date(file.lastModified());
            System.out.println("File: " + file.getName() + ", Date: " + lastMod + "");
        }
private static List<File> sortByLastModified(String dirPath) {
    List<File> files = listFilesRec(dirPath);
    Collections.sort(files, new Comparator<File>() {
        public int compare(File o1, File o2) {
            return Long.compare(o1.lastModified(), o2.lastModified());
        }
    });
    return files;
}
Collections.sort(listFiles, new Comparator<File>() {
        public int compare(File f1, File f2) {
            return Long.compare(f1.lastModified(), f2.lastModified());
        }
    });

وحيث listFiles هو جمع كل الملفات في ArrayList

وجئت إلى هذا المنصب عندما كنت تبحث عن نفس الموضوع ولكن في android. أنا لا أقول هذا هو أفضل وسيلة للحصول على الملفات التي تم فرزها حسب تاريخ آخر تعديل، ولكن لها وأسهل طريقة وجدت حتى الان.

وفيما يلي الشفرة قد تكون مفيدة لشخص ما -

File downloadDir = new File("mypath");    
File[] list = downloadDir.listFiles();
    for (int i = list.length-1; i >=0 ; i--) {
        //use list.getName to get the name of the file
    }

والشكر

وهناك طريقة سهلة جدا ومريحة للتعامل مع المشكلة دون أي مقارنة إضافية. مجرد رمز تاريخ تعديل في سلسلة مع اسم الملف، ترتيب هذا الامر، وبعد تجريدها من جديد.

استخدم سلسلة من طول ثابت 20، ووضع تاريخ التعديل (الطويل) في ذلك، وملء مع الأصفار البادئة. ثم مجرد إلحاق اسم الملف إلى هذه السلسلة:

String modified_20_digits = ("00000000000000000000".concat(Long.toString(temp.lastModified()))).substring(Long.toString(temp.lastModified()).length()); 

result_filenames.add(modified_20_digits+temp.getAbsoluteFile().toString());

وماذا يحدث هذا هنا:

وFilename1: C: \ البيانات \ file1.html آخر تحديث: 1532914451455 آخر تعديل 20 سيارة: 00000001532914451455

وFilename1: C: \ البيانات \ file2.html آخر تحديث: 1532918086822 آخر تعديل 20 سيارة: 00000001532918086822

وتحول filnames إلى:

وFilename1: 00000001532914451455C: \ DATA \ file1.html

وFilename2: 00000001532918086822C: \ DATA \ file2.html

وبعد ذلك يمكنك فقط فرز هذه القائمة.

وكل ما عليك القيام به هو تجريد الأحرف 20 مرة أخرى في وقت لاحق (في جافا 8، يمكنك تجريدها لمجموعة كاملة مع خط واحد فقط باستخدام وظيفة .replaceAll)

وهناك أيضا بطريقة مختلفة تماما والتي قد تكون أكثر سهولة، ونحن لا نتعامل مع أعداد كبيرة.

وبدلا من فرز مجموعة كاملة بعد استرداد كافة أسماء وlastModified التواريخ، يمكنك فقط ضع كل اسم واحد فقط بعد استرجاعها في المكان المناسب من القائمة.

ويمكنك القيام بذلك من هذا القبيل:

list.add(1, object1)
list.add(2, object3)
list.add(2, object2)

وبعد إضافة object2 لموقف 2، وسوف تتحرك object3 لوضع 3.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top