जावा में फाइलों को सूचीबद्ध करने का सबसे अच्छा तरीका, दिनांक संशोधित द्वारा हल किया गया?


240

मैं एक निर्देशिका में फ़ाइलों की एक सूची प्राप्त करना चाहता हूं, लेकिन मैं इसे इस तरह क्रमबद्ध करना चाहता हूं कि सबसे पुरानी फाइलें पहले हैं। मेरा समाधान File.listFiles को कॉल करना था और बस File.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());
    } });

1
इस के "नए लंबे" भाग के साथ क्या है? आप केवल स्वयं की तुलना क्यों नहीं करते? कि आप केवल तुलना करने के लिए प्राप्त करने के लिए टन के टन बनाने से बचना होगा ...
जॉन गार्डनर

यह कोड संकलित नहीं करता है। तुलना के तरीकों की उम्मीद है कि वापसी एक लंबी के बजाय एक इंट है।
मारकोस्पेरेरा

1
क्या मैं एकमात्र ऐसा व्यक्ति हूं जो इस समाधान को पागल समझता है? आप file.lastModified()भारी मात्रा में कॉल कर रहे हैं । बेहतर है कि सभी तिथियां पहले प्राप्त करें और बाद में ऑर्डर करें, इसलिए file.lastModified()इसे केवल एक बार प्रति फ़ाइल कहा जाता है।
cccrack 12

1
आप अपाचे कॉमन्स तुलनित्र का उपयोग कर सकते हैं:Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
jlunavtgrad

5
जावा 8 के साथ एक बेहतर समाधान है (देखें Arrays.sort(files, Comparator.comparingLong(File::lastModified));
विन्किसुस्स

जवाबों:


99

मुझे लगता है कि आपका समाधान एकमात्र समझदार तरीका है। फ़ाइलों की सूची प्राप्त करने का एकमात्र तरीका File.listFiles () का उपयोग करना है और दस्तावेज़ीकरण बताता है कि यह फ़ाइलों के आदेश के बारे में कोई गारंटी नहीं देता है। इसलिए आपको एक तुलनित्र लिखने की आवश्यकता है जो File.lastModified () का उपयोग करता है और इसे पास करता है, फ़ाइलों की सरणी के साथ, Arrays.sort () में


मैं यहाँ प्रारूपण को कैसे ठीक करूँ? पूर्वावलोकन में ठीक लग रहा है, लेकिन 4 के लिंक खराब है।
डैन डायर

1
जबकि एक तुलना विधि उल्लंघन त्रुटि में अंतिम परिणाम छँटाई, देख File.lastModified बदल सकता है: stackoverflow.com/questions/20431031 देखें stackoverflow.com/a/4248059/314089 एक संभव बेहतर समाधान के लिए।
--सिरसोर

48

यदि आपके पास कई फाइलें हैं तो यह तेज हो सकता है। यह डेकोरेट-सॉर्ट-अघोषित पैटर्न का उपयोग करता है ताकि प्रत्येक फ़ाइल की अंतिम-संशोधित तिथि को हर बार के बजाय एक ही बार लाया जाए ताकि सॉर्ट एल्गोरिथ्म दो फ़ाइलों की तुलना करता है। यह संभावित रूप से I / O कॉल की संख्या को O (n log n) से O (n) तक कम कर देता है।

यह अधिक कोड है, हालांकि, इसका उपयोग केवल तभी किया जाना चाहिए यदि आप मुख्य रूप से गति से संबंधित हैं और यह औसत रूप से अभ्यास में तेज है (जिसे मैंने जांच लिया है)।

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;

5
सबसे अच्छा जवाब, क्योंकि यह संभवत: "कम्पेरिसन मेथड वायलेशन एरर" को रोकने वाला एकमात्र है यदि अंतिम सॉर्ट करते समय अंतिम बदलाव होता है?
--सिरसोर

1
यह भी इस्तेमाल किया जाना चाहिए जब आप तुलना विधि उल्लंघन के कारण IllegalArgumentException नहीं मिलने से चिंतित हों। मैप का उपयोग करने का तरीका विफल हो जाएगा यदि एक ही अंतिम फ़ाइल के साथ एक से अधिक फ़ाइल है, जिसके परिणामस्वरूप इन फ़ाइलों को छोड़ दिया जाएगा। यह निश्चित रूप से एक स्वीकृत उत्तर होना चाहिए।
एंड्रॉइड डेवलपर

44

जावा 8 के बाद से सुरुचिपूर्ण समाधान:

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

या, यदि आप इसे अवरोही क्रम में चाहते हैं, तो इसे उल्टा कर दें:

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

2
यह वास्तव में सबसे आसान उपाय है। सूचियों के लिए:files.sort(Comparator.comparingLong(File::lastModified));
starbroken

@starbroken आपका समाधान काम नहीं करता है यदि फ़ाइल एक साधारण सरणी है, जैसे फ़ाइल [], जो Directory.listFiles () द्वारा लौटा दी गई है।
विनिसीसुएस

@starbroken आपके समाधान के लिए काम करने के लिए, किसी को उपयोग करने की आवश्यकता है ArrayList<File> files = new ArrayList<File>(Arrays.asList(directory.listFiles())), जो कि केवल से आसान नहीं है File[] files = directory.listFiles()
विनिसीसुएस

हाँ, मैं आपसे सहमत हूँ। यदि आपके पास फ़ाइलों की एक सरणी है, तो सूची बनाने का कोई कारण नहीं है। (यदि कोई आश्चर्यचकित करता है, तो ArrayList<File>(...)viniciussss टिप्पणी में उस 'अतिरिक्त' को एक उत्परिवर्तित सूची प्राप्त करने की आवश्यकता होती है, जिसे क्रमबद्ध किया जा सकता है।) मुझे यह थ्रेड फ़ाइलों की सूची को सॉर्ट करने के तरीके की तलाश में मिला। इसलिए मैंने उस कोड को सिर्फ इसलिए जोड़ा ताकि लोग इसे सूची के रूप में अच्छी तरह से कॉपी कर सकें।
स्टारबोकन

Comparatorवर्ग किसी भी विधि कॉल नहीं हैcomparingLong
zeleven

37

समान दृष्टिकोण के बारे में क्या है, लेकिन लंबी वस्तुओं के लिए बॉक्सिंग के बिना:

File[] files = directory.listFiles();

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

यह केवल एपीआई 19+ लगता है।
गोबर

4
वापसी का उपयोग करें Long.valueOf (f1.lastModified ())। ComparTo (f2.lastModified ()); के बजाय कम एपीआई के लिए।
मार्टिन सैक्स

25

आप अपाचे कॉमन्स IO को भी देख सकते हैं , इसमें एक अंतर्निहित अंतिम संशोधित तुलनित्र है फाइलों के साथ काम करने के लिए और कई अन्य अच्छी उपयोगिताओं ।


5
इस समाधान के साथ javadoc में एक अजीब त्रुटि है, क्योंकि javadoc "LastModifiedFileComparator.LASTMODIFIED_COMPARATOR.sort (सूची);" किसी सूची को क्रमबद्ध करने के लिए, लेकिन LASTMODIFIED_COMPARATOR को "तुलनित्र <फ़ाइल>" के रूप में घोषित किया जाता है, इसलिए यह किसी भी "क्रमबद्ध" विधि को उजागर नहीं करता है।
ट्रिस्टन

4
इसे इस तरह से उपयोग करें: लिंक
cleroo

1
जबकि एक तुलना विधि उल्लंघन त्रुटि में अंतिम परिणाम छँटाई, देख File.lastModified बदल सकता है: stackoverflow.com/questions/20431031 देखें stackoverflow.com/a/4248059/314089 एक संभव बेहतर समाधान के लिए।
--सिरसोर

1
प्यार अपाचे कॉमन्स, कि बहुत समय बचा लिया,
RedDevil

16

जावा 8 में:

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


13

आयात:

org.apache.commons.io.comparator.LastModifiedFileComparator

अपाचे कॉमन्स

कोड:

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);

    }

यह तुरंत स्पष्ट नहीं है कि LastModifiedFileComparator.LASTMODIFIED_COMPARATOR को कहां से लिया गया है। शायद अपाचे कॉमन्स के लिंक जोड़ने से io को मदद मिलेगी।
ब्रॉडबैंड

हो गया, धन्यवाद ब्रॉडबैंड
बालाजी बोगाराम रामनारायण

10

यदि आप जो फाइलें छांट रहे हैं, उन्हें उसी समय संशोधित या अपडेट किया जा सकता है:


जावा 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;
}


ये दोनों समाधान निर्देशिका में प्रत्येक फ़ाइल के लिए एक निरंतर अंतिम संशोधित समय को बचाने के लिए एक अस्थायी मानचित्र डेटा संरचना बनाते हैं। इसका कारण हमें यह करने की आवश्यकता है कि यदि आपकी फ़ाइलों को अपडेट किया जा रहा है या संशोधित किया जा रहा है, जबकि आपकी तरह का प्रदर्शन किया जा रहा है, तो आपका तुलनित्र तुलनित्र इंटरफ़ेस के सामान्य अनुबंध की ट्रांज़ेक्शन आवश्यकता का उल्लंघन कर रहा होगा क्योंकि तुलना के दौरान अंतिम संशोधित समय बदल सकता है।

यदि, दूसरी ओर, आप जानते हैं कि आपके सॉर्ट के दौरान फाइलें अपडेट या संशोधित नहीं होंगी, तो आप इस प्रश्न के लिए प्रस्तुत किए गए किसी भी अन्य उत्तर के साथ दूर हो सकते हैं, जिनमें से मैं आंशिक रूप से निम्नलिखित हूं:

जावा 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)
            .sorted(Comparator.comparing(File::lastModified))
            .map(File::toPath)  // remove this line if you would rather work with a List<File> instead of List<Path>
            .collect(Collectors.toList());
    }
}

नोट: मुझे पता है कि आप उपरोक्त उदाहरणों में फ़ाइल ऑब्जेक्ट्स से फ़ाइल ऑब्जेक्ट्स में अनुवाद से बच सकते हैं :: getLastModifiedTime api को सॉर्ट स्ट्रीम ऑपरेशन में, फिर भी, आपको अपने लैम्ब्डा के अंदर चेक किए गए IO अपवादों से निपटने की आवश्यकता है जो हमेशा एक दर्द होता है। । मैं कहूंगा कि यदि प्रदर्शन पर्याप्त रूप से महत्वपूर्ण है कि अनुवाद अस्वीकार्य है, तो मैं या तो लेम्बडा में चेक किए गए IOException के साथ इसे अनचेक किए गए अपवाद के रूप में प्रचारित करूंगा या मैं फ़ाइलों को पूरी तरह से अप्रूव कर दूंगा और फ़ाइल ऑब्जेक्ट्स के साथ सौदा करूंगा:

final List<File> sorted = Arrays.asList(new File(directoryPathString).listFiles());
sorted.sort(Comparator.comparing(File::lastModified));

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

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

1
यह वास्तव में उस दिनांक संशोधित संपत्ति पर सॉर्ट नहीं करता है जिसे प्रश्न में उल्लेखित किया गया था। सॉर्ट फ़ंक्शन फ़ाइल ऑब्जेक्ट के प्राकृतिक आदेश का उपयोग करेगा जो पथ के नाम पर सिस्टम-निर्भर लेक्सिकोग्राफ़िक है
मैट चान

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

जहां listFilesArrayList में सभी फाइलों का संग्रह है


1

आप अमरूद ऑर्डर करने की कोशिश कर सकते हैं :

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);

1

आप Apache 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 + "");
        }

1
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;
}

0

मैं इस पोस्ट पर आया था जब मैं एक ही मुद्दे के लिए खोज रहा था, लेकिन में 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
    }

धन्यवाद


लेकिन छँटाई कौन करता है?
DAB

forलूप के आरंभीकरण भाग में आप देख सकते हैं कि मैंने ऊपर ले लिया list.length-1है i >=0जो आपको रिवर्स ऑर्डर में सीधे पुनरावृत्त करता है।
ह्रदयेश विश्वदेवा

0

किसी भी अतिरिक्त तुलनित्र के बिना समस्या को संभालने का एक बहुत आसान और सुविधाजनक तरीका है। बस फ़ाइल नाम के साथ स्ट्रिंग में संशोधित दिनांक को कोड करें, इसे सॉर्ट करें, और बाद में इसे फिर से बंद कर दें।

निर्धारित लंबाई 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: \ data \ file1.html अंतिम संशोधित: 1532914451455 अंतिम संशोधित 20 अंक: 00000001532914451455

Filename1: C: \ data \ file2.html अंतिम संशोधित: 1532918086822 अंतिम संशोधित 20 अंक: 00000001532918086822

फिल्म्स को इसमें रूपांतरित करता है:

Filename1: 00000001532914451455C: \ data \ file1.html

Filename2: 00000001532918086822C: \ data \ file2.html

फिर आप इस सूची को क्रमबद्ध कर सकते हैं।

आपको केवल 20 वर्णों को बाद में फिर से पट्टी करने की आवश्यकता है (जावा 8 में, आप .replaceAll फ़ंक्शन का उपयोग करके पूरे ऐरे के साथ इसे केवल एक पंक्ति के लिए पट्टी कर सकते हैं)।


-1

वहाँ भी एक पूरी तरह से अलग तरीका है जो और भी आसान हो सकता है, क्योंकि हम बड़ी संख्या के साथ सौदा नहीं करते हैं।

सभी फ़ाइल नाम और अंतिम तिथियों को पुनः प्राप्त करने के बाद पूरे सरणी को छाँटने के बजाय, आप सूची के सही स्थान पर पुनः प्राप्त करने के बाद हर एक फ़ाइल नाम को सम्मिलित कर सकते हैं।

आप इसे इस तरह से कर सकते हैं:

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

ऑब्जेक्ट 2 को स्थिति 2 में जोड़ने के बाद, यह ऑब्जेक्ट 3 को स्थिति 3 में ले जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.