Java, Chỉ liệt kê các thư mục con từ một thư mục, không phải tệp


100

Trong Java, Làm cách nào để liệt kê chỉ các thư mục con từ một thư mục?

Tôi muốn sử dụng chức năng java.io.File, phương pháp tốt nhất trong Java để thực hiện việc này là gì?

Câu trả lời:


141

Bạn có thể sử dụng lớp Tệp để liệt kê các thư mục.

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

Cập nhật

Nhận xét từ tác giả về bài đăng này muốn một cách nhanh hơn, thảo luận tuyệt vời ở đây: Làm thế nào để truy xuất danh sách thư mục NHANH CHÓNG trong Java?

Về cơ bản:

  1. Nếu bạn kiểm soát cấu trúc tệp, tôi sẽ cố gắng tránh rơi vào tình huống đó.
  2. Trong Java NIO.2, bạn có thể sử dụng hàm thư mục để trả về một trình lặp để cho phép mở rộng quy mô lớn hơn. Lớp dòng thư mục là một đối tượng mà bạn có thể sử dụng để lặp lại các mục trong một thư mục.

xin chào, cảm ơn đã trả lời. Nhưng tôi không phải lặp lại tất cả các mục trong một thư mục. Tôi phải liệt kê trực tiếp thư mục con từ thư mục. B'coz Tôi có rất nhiều tệp và chỉ có một số thư mục con trong một thư mục, vì vậy, việc kiểm tra isDirectory () rất mất thời gian. vui lòng trả lời tôi theo cách khác.
Lokesh Paunikar

Tôi đã cập nhật bài đăng của mình, đặc biệt, hãy xem bình luận của Jon Skeet về câu hỏi. Và phản hồi NIO vì Java NIO 2 có một trình vòng lặp cho hàm thư mục trả về một luồng thư mục.
Mohamed Mansour

Bạn đang đề cập đến nhận xét Skeet nào? Câu trả lời hoạt động tốt hơn ở đây là gì?
Stealth Rabbi lúc

107

Một giải pháp Java 8 rất đơn giản:

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

Nó tương đương với việc sử dụng FileFilter (cũng hoạt động với Java cũ hơn):

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

4
Dấu hai chấm ::hoạt động như thế nào trong trường hợp này?
snickers

Tôi nhận thấy rằng không có câu trả lời nào khác sử dụng FileFilter vì vậy tôi đã thêm phiên bản tương đương mà không sử dụng tham chiếu phương thức. Để biết thêm về tham chiếu phương pháp, hãy tham khảo câu hỏi SO này hoặc bài viết này .
headsvk

điều này có nhận được các thư mục con hay chỉ các thư mục trực tiếp dưới / your / path /?
amadain

@amadain không có đệ quy như mong đợi docs.oracle.com/javase/7/docs/api/java/io/File.html#listFiles ()
headsvk

14

@Mohamed Mansour bạn gần như đã ở đó ... đối số "dir" mà bạn đang sử dụng thực sự là đường dẫn chữa bệnh, vì vậy nó sẽ luôn trả về true. Để xem con đó có phải là một thư mục con hay không, bạn cần phải kiểm tra con đó.

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

Trong trường hợp bạn quan tâm đến một giải pháp sử dụng Java 7 và NIO.2, nó có thể như sau:

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

Xin chào và chào mừng bạn đến với StackOverflow! Bạn có thể nói rõ hơn về câu trả lời của bạn một chút không? Giống như giải thích các phần thú vị trong đoạn mã của bạn hoặc liên kết đến tài liệu để đọc sau này?
Richard-Degenne

Đây phải là câu trả lời chính xác vì nó cung cấp đối tượng Tệp với Đường dẫn hợp quy hoàn chỉnh. Đây có thể là cũ nhưng nó có giá trị chỉ ra điều này
Jero Dungog

2

Đối với những người quan tâm đến Java 7 và NIO, có một giải pháp thay thế cho câu trả lời của @ voo ở trên . Chúng ta có thể sử dụng try-with-resources để gọi Files.find()và hàm lambda được sử dụng để lọc các thư mục.

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) {
    ...
}

Chúng tôi thậm chí có thể lọc các thư mục theo tên bằng cách thay đổi hàm lambda:

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

hoặc theo ngày:

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

Tôi muốn sử dụng chức năng java.io.File,

Vào năm 2012 (ngày của câu hỏi) có, không phải ngày hôm nay. java.nioAPI phải được ưu tiên cho các yêu cầu như vậy.

Kinh khủng với rất nhiều câu trả lời, nhưng không phải là cách đơn giản mà tôi sẽ sử dụng Files.walk().filter().collect().

Trên toàn cầu có thể có hai cách tiếp cận:

1) Files.walk(Path start, )không có maxDepthgiới hạn trong khi

2) Files.walk(Path start, int maxDepth, FileVisitOption... options)cho phép thiết lập nó.

Không chỉ định bất kỳ giới hạn độ sâu nào, nó sẽ cung cấp:

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

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

Và nếu vì lý do kế thừa, bạn cần có Danh sách Filebạn có thể thêm map(Path::toFile)thao tác trước khi thu thập:

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
}

Cũng có Files.list(Path)mà có lẽ giống như Files.walk(Path,1).
David L.

@David L Thật vậy Files.list(Path)là một lựa chọn thay thế hợp lý nếu chúng ta không muốn lặp lại các thư mục một cách đệ quy. Để lặp lại các thư mục một cách đệ quy, walk()phù hợp hơn.
davidxxx

1

Giải pháp làm việc cho tôi, bị thiếu trong danh sách các câu trả lời. Do đó tôi đăng giải pháp này ở đây:

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

Ở đây tôi đã sử dụng org.apache.commons.io.filefilter.FileFilterUtilstừ Apache commons-io-2.2.jar. Tài liệu của nó có sẵn tại đây: https://commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/filefilter/FileFilterUtils.html


0

Cho một thư mục bắt đầu dưới dạng String

  1. Tạo một phương thức lấy một Stringđường dẫn làm tham số. Trong phương pháp:
  2. Tạo một đối tượng Tệp mới dựa trên thư mục bắt đầu
  3. Lấy một mảng tệp trong thư mục hiện tại bằng listFilesphương pháp
  4. Lặp lại mảng tệp
    1. Nếu đó là một tệp, hãy tiếp tục lặp lại
    2. Nếu đó là một thư mục, hãy in ra tên và đệ quy lại trên đường dẫn thư mục mới này

xin chào, cảm ơn đã trả lời. Nhưng tôi không phải lặp lại tất cả các mục trong một thư mục. Tôi phải liệt kê trực tiếp thư mục con từ thư mục. B'coz Tôi có rất nhiều tệp và chỉ có một số thư mục con trong một thư mục, vì vậy, việc kiểm tra isDirectory () rất mất thời gian. vui lòng trả lời tôi theo cách khác.
Lokesh Paunikar

0

Đây là giải pháp cho mã của tôi. Tôi vừa thực hiện một sự thay đổi nhỏ so với câu trả lời đầu tiên . Điều này sẽ liệt kê tất cả các thư mục chỉ trong từng dòng thư mục mong muốn:

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!");
        }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.