Java แสดงเฉพาะไดเร็กทอรีย่อยจากไดเร็กทอรีไม่ใช่ไฟล์


102

ใน Java ฉันจะแสดงเฉพาะไดเร็กทอรีย่อยจากไดเร็กทอรีได้อย่างไร?

ฉันต้องการใช้ฟังก์ชัน java.io.File วิธีใดที่ดีที่สุดใน Java ในการทำสิ่งนี้

คำตอบ:


143

คุณสามารถใช้คลาสFileเพื่อแสดงรายการไดเร็กทอรี

File file = new File("/path/to/directory");
String[] directories = file.list(new FilenameFilter() {
  @Override
  public boolean accept(File current, String name) {
    return new File(current, name).isDirectory();
  }
});
System.out.println(Arrays.toString(directories));

อัปเดต

ความคิดเห็นจากผู้เขียนในโพสต์นี้ต้องการวิธีที่เร็วขึ้นการสนทนาที่ยอดเยี่ยมที่นี่: จะดึงรายการไดเรกทอรีอย่างรวดเร็วใน Java ได้อย่างไร?

โดยทั่วไป:

  1. หากคุณควบคุมโครงสร้างไฟล์ฉันจะพยายามหลีกเลี่ยงไม่ให้เข้าสู่สถานการณ์นั้น
  2. ใน Java NIO.2 คุณสามารถใช้ฟังก์ชันไดเร็กทอรีเพื่อส่งคืนตัววนซ้ำเพื่อให้สามารถปรับขนาดได้มากขึ้น ไดเร็กทอรีสตรีมคลาสเป็นอ็อบเจ็กต์ที่คุณสามารถใช้เพื่อทำซ้ำบนรายการในไดเร็กทอรี

สวัสดีขอบคุณสำหรับการตอบกลับ แต่ฉันไม่ต้องวนซ้ำรายการทั้งหมดในไดเร็กทอรี ฉันต้องแสดงรายการไดเร็กทอรีย่อยโดยตรงจากไดเร็กทอรี B'coz ฉันมีไฟล์จำนวนมากและมีไดเร็กทอรีย่อยเพียงไม่กี่ไดเร็กทอรีดังนั้นการตรวจสอบ isDirectory () จึงใช้เวลานาน โปรดตอบฉันด้วยวิธีอื่น
Lokesh Paunikar

ฉันอัปเดตโพสต์ของฉันโดยเฉพาะอย่างยิ่งลองดูความคิดเห็นของ Jon Skeet ในคำถาม และการตอบสนอง NIO เนื่องจาก Java NIO 2 มีตัววนซ้ำสำหรับฟังก์ชันไดเร็กทอรีที่ส่งคืนสตรีมของไดเร็กทอรี
Mohamed Mansour

คุณหมายถึงความคิดเห็นของ Skeet อะไร? คำตอบที่มีประสิทธิภาพดีกว่าที่นี่คืออะไร?
ชิงทรัพย์รับบี

108

โซลูชัน Java 8 ที่ง่ายมาก:

File[] directories = new File("/your/path/").listFiles(File::isDirectory);

เทียบเท่ากับการใช้ FileFilter (ทำงานกับ Java รุ่นเก่าได้เช่นกัน):

File[] directories = new File("/your/path/").listFiles(new FileFilter() {
    @Override
    public boolean accept(File file) {
        return file.isDirectory();
    }
});

5
เครื่องหมายทวิภาคคู่::ทำงานอย่างไรในอินสแตนซ์นี้
snickers10m

ฉันสังเกตเห็นว่าไม่มีคำตอบอื่นใดที่ใช้ FileFilter ดังนั้นฉันจึงเพิ่มเวอร์ชันที่เทียบเท่าโดยไม่ใช้การอ้างอิงวิธีการ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการอ้างอิงวิธีการพูดถึงเรื่องนี้คำถาม SOหรือนี้บทความ
Headsvk

สิ่งนี้ได้รับไดเรกทอรีย่อยหรือเพียงแค่ไดเร็กทอรีโดยตรงภายใต้ / your / path /?
amadain

@amadain ไม่มีการเรียกซ้ำตามที่คาดไว้docs.oracle.com/javase/7/docs/api/java/io/File.html#listFiles ()
Headsvk

14

@ Mohamed Mansour คุณเกือบจะอยู่ที่นั่นแล้ว ... อาร์กิวเมนต์ "dir" จากที่คุณใช้นั้นเป็นเส้นทางที่รักษาได้ดังนั้นมันจะกลับมาเป็นจริงเสมอ หากต้องการดูว่าเด็กเป็นไดเร็กทอรีย่อยหรือไม่คุณต้องทดสอบเด็กนั้น

File file = new File("/path/to/directory");
String[] directories = file.list(new FilenameFilter() {
  @Override
  public boolean accept(File current, String name) {
    return new File(current, name).isDirectory();
  }
});
System.out.println(Arrays.toString(directories));

7

ในกรณีที่คุณสนใจโซลูชันโดยใช้ Java 7 และ NIO.2 อาจเป็นดังนี้:

private static class DirectoriesFilter implements Filter<Path> {
    @Override
    public boolean accept(Path entry) throws IOException {
        return Files.isDirectory(entry);
    }
}

try (DirectoryStream<Path> ds = Files.newDirectoryStream(FileSystems.getDefault().getPath(root), new DirectoriesFilter())) {
        for (Path p : ds) {
            System.out.println(p.getFileName());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

3
ArrayList<File> directories = new ArrayList<File>(
    Arrays.asList(
        new File("your/path/").listFiles(File::isDirectory)
    )
);

สวัสดีและยินดีต้อนรับสู่ StackOverflow! คุณสามารถอธิบายรายละเอียดเกี่ยวกับคำตอบของคุณได้ไหม เช่นเดียวกับการอธิบายส่วนที่น่าสนใจของข้อมูลโค้ดของคุณหรือเชื่อมโยงไปยังเอกสารประกอบเพื่อการอ่านเพิ่มเติม
Richard-Degenne

นี่ควรเป็นคำตอบที่ถูกต้องเนื่องจากให้อ็อบเจ็กต์ File พร้อม Canonical Path ที่สมบูรณ์ อาจจะเก่า แต่ก็คุ้มที่จะชี้ให้เห็น
Jero Dungog

2

สำหรับผู้ที่มีความสนใจใน Java NIO 7 และจะมีวิธีการแก้ปัญหาทางเลือกให้กับคำตอบของ @ Voo ดังกล่าวข้างต้น เราสามารถใช้try-with-resourcesที่เรียกใช้Files.find()และฟังก์ชันแลมบ์ดาที่ใช้เพื่อกรองไดเร็กทอรี

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;


final Path directory = Paths.get("/path/to/folder");

try (Stream<Path> paths = Files.find(directory, Integer.MAX_VALUE, (path, attributes) -> attributes.isDirectory())) {
    paths.forEach(System.out::println);
} catch (IOException e) {
    ...
}

เรายังสามารถกรองไดเรกทอรีตามชื่อได้โดยเปลี่ยนฟังก์ชันแลมบ์ดา:

(path, attributes) -> attributes.isDirectory() && path.toString().contains("test")

หรือตามวันที่:

final long now = System.currentTimeMillis();
final long yesterday = new Date(now - 24 * 60 * 60 * 1000L).getTime();

// modified in the last 24 hours
(path, attributes) -> attributes.isDirectory() && attributes.lastModifiedTime().toMillis() > yesterday

2

ฉันต้องการใช้ฟังก์ชัน java.io.File

ในปี 2012 (วันที่ของคำถาม) ใช่ไม่ใช่วันนี้ java.nioต้องได้รับการสนับสนุน API สำหรับข้อกำหนดดังกล่าว

แย่มากกับคำตอบมากมาย แต่ไม่ใช่วิธีง่ายๆที่ฉันจะใช้นั่นคือ Files.walk().filter().collect()แต่ไม่ได้เป็นวิธีง่ายๆที่ผมจะใช้ที่อยู่

เป็นไปได้สองแนวทางทั่วโลก:

1) Files.walk(Path start, )ไม่มีmaxDepthข้อ จำกัด ในขณะที่

2)Files.walk(Path start, int maxDepth, FileVisitOption... options)อนุญาตให้ตั้งค่า

โดยไม่ระบุข้อ จำกัด เชิงลึกใด ๆ จะให้:

Path directory = Paths.get("/foo/bar");

try {
    List<Path> directories =
            Files.walk(directory)
                 .filter(Files::isDirectory)
                 .collect(Collectors.toList());
} catch (IOException e) {
    // process exception
}

และหากเหตุผลเดิมคุณต้องได้รับรายชื่อFileคุณสามารถเพิ่มการmap(Path::toFile)ดำเนินการก่อนการรวบรวม:

Path directory = Paths.get("/foo/bar");

try {
    List<File> directories =
            Files.walk(directory)
                 .filter(Files::isDirectory)
                 .map(Path::toFile)
                 .collect(Collectors.toList());
} catch (IOException e) {
    // process exception
}

นอกจากนี้ยังมีซึ่งอาจเป็นเช่นเดียวกับFiles.list(Path) Files.walk(Path,1)
David L.

@David L แน่นอนFiles.list(Path)เป็นทางเลือกที่ยุติธรรมหากเราไม่ต้องการวนซ้ำโฟลเดอร์ ในการวนซ้ำโฟลเดอร์แบบวนซ้ำให้walk()เหมาะกว่า
davidxxx

1

วิธีแก้ปัญหาที่ใช้ได้ผลสำหรับฉันหายไปจากรายการคำตอบ ดังนั้นฉันจึงโพสต์วิธีแก้ปัญหานี้ที่นี่:

File[]dirs = new File("/mypath/mydir/").listFiles((FileFilter)FileFilterUtils.directoryFileFilter());

ที่นี่ฉันใช้org.apache.commons.io.filefilter.FileFilterUtilsจาก Apache commons-io-2.2.jar เอกสารประกอบมีอยู่ที่นี่: https://commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/filefilter/FileFilterUtils.html


0

กำหนดไดเร็กทอรีเริ่มต้นเป็นไฟล์ String

  1. สร้างวิธีการที่ใช้ Stringพา ธ เป็นพารามิเตอร์ ในวิธีการ:
  2. สร้างไฟล์ใหม่อ็อบเจ็กต์ตามไดเร็กทอรีเริ่มต้น
  3. รับอาร์เรย์ของไฟล์ในไดเร็กทอรีปัจจุบันโดยใช้ไฟล์ listFilesเมธอด
  4. วนซ้ำอาร์เรย์ของไฟล์
    1. หากเป็นไฟล์ให้วนลูปต่อ
    2. ถ้ามันไดเรกทอรีพิมพ์ชื่อและrecurseบนเส้นทางไดเรกทอรีใหม่นี้

สวัสดีขอบคุณสำหรับการตอบกลับ แต่ฉันไม่ต้องวนซ้ำรายการทั้งหมดในไดเร็กทอรี ฉันต้องแสดงรายการไดเร็กทอรีย่อยโดยตรงจากไดเร็กทอรี B'coz ฉันมีไฟล์จำนวนมากและมีไดเร็กทอรีย่อยเพียงไม่กี่ไดเร็กทอรีดังนั้นการตรวจสอบ isDirectory () จึงใช้เวลานาน โปรดตอบฉันด้วยวิธีอื่น
Lokesh Paunikar

0

นี่คือวิธีแก้ปัญหาสำหรับรหัสของฉัน ผมก็ไม่ได้มีการเปลี่ยนแปลง litlle จากคำตอบแรก สิ่งนี้จะแสดงรายการโฟลเดอร์ทั้งหมดในไดเรกทอรีที่ต้องการทีละบรรทัดเท่านั้น:

try {
            File file = new File("D:\\admir\\MyBookLibrary");
            String[] directories = file.list(new FilenameFilter() {
              @Override
              public boolean accept(File current, String name) {
                return new File(current, name).isDirectory();
              }
            });
            for(int i = 0;i < directories.length;i++) {
                if(directories[i] != null) {
                    System.out.println(Arrays.asList(directories[i]));

                }
            }
        }catch(Exception e) {
            System.err.println("Error!");
        }

0

คุณสามารถใช้ API ไฟล์ JAVA 7

Path myDirectoryPath = Paths.get("path to my directory");
List<Path> subDirectories = Files.find(
                    myDirectoryPath ,
                    Integer.MAX_VALUE,
                    (filePath, fileAttr) -> fileAttr.isDirectory() && !filePath.equals(myDirectoryPath )
            ).collect(Collectors.toList());

หากคุณต้องการค่าเฉพาะคุณสามารถเรียกใช้แผนที่ด้วยค่าที่คุณต้องการก่อนที่จะรวบรวมข้อมูล


0
    File files = new File("src");
    // src is folder name...
    //This will return the list of the subDirectories
    List<File> subDirectories = Arrays.stream(files.listFiles()).filter(File::isDirectory).collect(Collectors.toList());
// this will print all the sub directories
Arrays.stream(files.listFiles()).filter(File::isDirectory).forEach(System.out::println);

0

นี่จะแสดงรายการ (นั่นคือพิมพ์) ไดเรกทอรีย่อยทั้งหมดอย่างแท้จริง โดยพื้นฐานแล้วเป็นแบบวนซ้ำที่คุณไม่จำเป็นต้องจัดเก็บรายการระหว่างกันในรายการ นี่คือสิ่งที่น่าจะต้องการมากที่สุดดังนั้นฉันจึงปล่อยไว้ที่นี่

Path directory = Paths.get("D:\\directory\\to\\list");

Files.walk(directory, 1).filter(entry -> !entry.equals(directory))
    .filter(Files::isDirectory).forEach(subdirectory ->
{
    // do whatever you want with the subdirectories
    System.out.println(subdirectory.getFileName());
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.