2010-07-01 15 views
130

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

उत्तर

166

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

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

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 के प्रति संवेदनशील है जब पेड़ JVM के ढेर धारण कर सकते हैं की तुलना में गहरी है। आप इसके बजाय एक पुनरावृत्ति दृष्टिकोण या tail-recursion का उपयोग करना चाह सकते हैं, लेकिन यह एक और विषय है;)

+0

धन्यवाद बलस, किसी भी विचार पर कि यह सामान्य अनुमान के रूप में कितना गहरा हो सकता है? – James

+9

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

+3

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

1

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

25

चेक - विशेष रूप से iterateFiles:

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

+4

यह API सही मायने में नहीं स्ट्रीमिंग है (यदि आप mem उपयोग के बारे में परवाह है), यह पहली बार संग्रह उत्पन्न लागू किया जा सकता है, तो ही इस पर एक iterator देता है: वापसी listFiles (निर्देशिका, fileFilter , dirfilter) .iterator(); जावा 1.6 के लिए –

+0

अच्छा विकल्प। –

1

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

listFiles() 

को देखने के लिए जावा फ़ाइल एपीआई here में कर सकते हैं। यह निर्देशिका में सभी फ़ाइलों की एक सरणी देता है। इसका उपयोग

isDirectory() 

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

+0

लिंक टूटा हुआ ... !!! –

+0

यह [लिंक] (https://docs.oracle.com/javase/8/docs/api/java/io/File.html) उपयोग में हो सकता है क्योंकि उत्तर में से एक टूटा हुआ है। – Donglecow

65

यदि आप जावा 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(); 
    } 
    } 

} 
+0

क्या कोई नई निर्देशिका चलने पर और फ़ंक्शन निष्पादित करने के दौरान धाराओं को चेकपॉइंट लगाने का कोई तरीका है? –

5

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

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

6

जावा 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; 
} 
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; 
     } 
}); 
संबंधित मुद्दे

 संबंधित मुद्दे