मैं जावा में निर्देशिका में फ़ाइलों के माध्यम से पुनरावृति कैसे करूं?


175

मुझे निर्देशिका की सभी फाइलों की सूची प्राप्त करने की आवश्यकता है, जिसमें सभी उप-निर्देशिकाओं में फाइलें भी शामिल हैं। जावा के साथ निर्देशिका पुनरावृत्ति को पूरा करने का मानक तरीका क्या है?

जवाबों:


207

File#isDirectory()यदि दी गई फ़ाइल (पथ) एक निर्देशिका है, तो आप परीक्षण करने के लिए उपयोग कर सकते हैं । यदि यह है true, तो आप इसके File#listFiles()परिणाम के साथ फिर से उसी विधि को कॉल करते हैं । इसे रिकर्सन कहते हैं ।

यहाँ एक बुनियादी किकऑफ उदाहरण है।

public static void main(String... args) {
    File[] files = new File("C:/").listFiles();
    showFiles(files);
}

public static void showFiles(File[] files) {
    for (File file : files) {
        if (file.isDirectory()) {
            System.out.println("Directory: " + file.getName());
            showFiles(file.listFiles()); // Calls same method again.
        } else {
            System.out.println("File: " + file.getName());
        }
    }
}

ध्यान दें कि यह StackOverflowErrorतब संवेदनशील होता है जब पेड़ जेवीएम के ढेर से गहरा हो। आप इसके बजाय एक पुनरावृत्त दृष्टिकोण या पूंछ- पुनरावृत्ति का उपयोग करना चाह सकते हैं , लेकिन यह एक और विषय है;)


धन्यवाद Balus, एक सामान्य अनुमान के रूप में कितना गहरा हो सकता है पर कोई विचार?
जेम्स

10
आपके JVM की मेमोरी सेटिंग्स पर निर्भर करता है। लेकिन आम तौर पर कुछ हजार की तरह। अगर आपको लगता है कि आप कभी भी इस तरह एक निर्देशिका में भाग सकते हैं, तो पुनरावृत्ति का उपयोग न करें।
माइक बैरनज़क

4
यह NullPointerExceptionतब होता है जब कॉल के बीच फाइल सिस्टम बदल जाता है isDirectoryऔर ब्लॉक या आप वास्तव में अशुभ listFilesहो जाते हैं, तो ऐसा होने की संभावना है System.out.println। जाँच रहा है कि उत्पादन listFilesशून्य है कि दौड़ की स्थिति का समाधान होगा।
माइक सैमुअल

1
@BoratSagdiyev, पुराने जावा फ़ाइल API का उपयोग नहीं कर रहा है, लेकिन यदि आप एक आधुनिक JVM पर हैं, तो आपको java.nio.file.DirectoryStreamएक निर्देशिका पर पुनरावृति करने की अनुमति देता है, और एक छोटी मेमोरी फ़ुटप्रिंट लागू किया जा सकता है, लेकिन यह सुनिश्चित करने का एकमात्र तरीका होगा किसी विशेष प्लेटफ़ॉर्म पर मेमोरी उपयोग की निगरानी के लिए।
माइक शमूएल

1
"C: \\" फ़ोल्डर एक उदाहरण का सबसे अच्छा विकल्प नहीं है)
व्याचेस्लाव

86

यदि आप जावा 1.7 का उपयोग कर रहे हैं, तो आप उपयोग कर सकते हैं java.nio.file.Files.walkFileTree(...)

उदाहरण के लिए:

public class WalkFileTreeExample {

  public static void main(String[] args) {
    Path p = Paths.get("/usr");
    FileVisitor<Path> fv = new SimpleFileVisitor<Path>() {
      @Override
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
          throws IOException {
        System.out.println(file);
        return FileVisitResult.CONTINUE;
      }
    };

    try {
      Files.walkFileTree(p, fv);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}

यदि आप जावा 8 का उपयोग कर रहे हैं, तो आप स्ट्रीम इंटरफ़ेस का उपयोग कर सकते हैं java.nio.file.Files.walk(...):

public class WalkFileTreeExample {

  public static void main(String[] args) {
    try (Stream<Path> paths = Files.walk(Paths.get("/usr"))) {
      paths.forEach(System.out::println);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}

1
क्या नई दिशा में चलने और किसी कार्य को अंजाम देने के लिए एक चौकी लगाने के लिए धाराओं के साथ एक रास्ता है?
रघु डीवी

28

Apache Commons में विशेष रूप से iterateFiles में FileUtils वर्ग की जाँच करें :

दी गई निर्देशिका में फ़ाइलों पर पुनरावृत्ति की अनुमति देता है (और वैकल्पिक रूप से इसके उपनिर्देशिका)।


5
यह API सही मायने में स्ट्रीमिंग नहीं है (यदि आप मेम उपयोग के बारे में परवाह करते हैं), तो यह पहले एक संग्रह उत्पन्न करता है, उसके बाद ही एक पुनरावृत्ति देता है: रिटर्न लिस्ट फ़ाइल्स (डायरेक्टरी, फाइलफ़िल्टर, डीरफ़िल्टर) .iterator ()।
गिली नाचुम

जावा 1.6 के लिए अच्छा विकल्प।
डेविड आई।

@GiliNachum से सहमत हैं। अपाचे द्वारा FileUtils पहले सभी फाइलों को इकट्ठा करता है और उनके लिए एक पुनरावृत्ति देता है। यदि आपके पास भारी मात्रा में फाइलें हैं, तो यह संसाधनों के लिए हानिकारक है।
बजे बोगदान समोंड्रो

8

जावा 7+ के लिए, https://docs.oracle.com/javase/7/docs/api/java/nio/file/DirectoryStream.html भी है

जावदोक से लिया गया उदाहरण:

List<Path> listSourceFiles(Path dir) throws IOException {
   List<Path> result = new ArrayList<>();
   try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{c,h,cpp,hpp,java}")) {
       for (Path entry: stream) {
           result.add(entry);
       }
   } catch (DirectoryIteratorException ex) {
       // I/O error encounted during the iteration, the cause is an IOException
       throw ex.getCause();
   }
   return result;
}

8

का उपयोग करते हुए org.apache.commons.io.FileUtils

File file = new File("F:/Lines");       
Collection<File> files = FileUtils.listFiles(file, null, true);     
for(File file2 : files){
    System.out.println(file2.getName());            
} 

यदि आप उप निर्देशिकाओं से फ़ाइलें नहीं चाहते हैं तो गलत का उपयोग करें।


3

यह एक पेड़ है, इसलिए पुनरावृत्ति आपका मित्र है: माता-पिता की निर्देशिका से शुरू करें और बच्चे की फ़ाइलों की एक सरणी प्राप्त करने के लिए विधि को कॉल करें। बाल सरणी के माध्यम से Iterate। यदि वर्तमान मान एक निर्देशिका है, तो इसे अपनी विधि के पुनरावर्ती कॉल में पास करें। यदि नहीं, तो पत्ती फ़ाइल को उचित रूप से संसाधित करें।


2

जैसा कि कहा गया है, यह एक पुनरावृत्ति समस्या है। विशेष रूप से, आप देखना चाह सकते हैं

listFiles() 

यहाँ जावा फ़ाइल एपीआई में । यह एक डायरेक्टरी में सभी फाइलों की एक सरणी देता है। इसके साथ ही उपयोग करना

isDirectory()

यह देखने के लिए कि क्या आपको फिर से शुरू करने की आवश्यकता है, एक अच्छी शुरुआत है।


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

0

@Msandiford उत्तर के साथ जोड़ने के लिए, जब किसी फ़ाइल ट्री को यू चलाया जाता है, तो अधिकतर किसी कार्य को निर्देशिका या किसी विशेष फ़ाइल के रूप में निष्पादित करना चाहते हैं। यदि आप स्ट्रीम का उपयोग करने में अनिच्छुक हैं। ओवरराइड की गई निम्नलिखित विधियों को लागू किया जा सकता है

Files.walkFileTree(Paths.get(Krawl.INDEXPATH), EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
    new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                throws IOException {
                // Do someting before directory visit
                return FileVisitResult.CONTINUE;
        }
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                throws IOException {
                // Do something when a file is visited
                return FileVisitResult.CONTINUE;
        }
        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc)
                throws IOException {
                // Do Something after directory visit 
                return FileVisitResult.CONTINUE;
        }
});

0

आप फ़ाइल ट्रैवर्सल के लिए File.list (FilenameFilter) (और वेरिएंट) का भी दुरुपयोग कर सकते हैं। लघु कोड और प्रारंभिक जावा संस्करणों में काम करता है, जैसे:

// list files in dir
new File(dir).list(new FilenameFilter() {
    public boolean accept(File dir, String name) {
        String file = dir.getAbsolutePath() + File.separator + name;
        System.out.println(file);
        return false;
    }
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.