Java, Dosyaları değil, dizindeki yalnızca alt dizinleri listele


100

Java'da, bir dizinden yalnızca alt dizinleri nasıl listeleyebilirim?

Java.io.File işlevselliğini kullanmak istiyorum, bunu yapmak için Java'da en iyi yöntem nedir?

Yanıtlar:


141

Sen kullanabilirsiniz Dosya dizinleri listelemek için sınıf.

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

Güncelleme

Yazarın bu gönderiye yaptığı yorum burada daha hızlı bir yol, harika bir tartışma istedi: Java'da dizinlerin bir listesini HIZLI bir şekilde nasıl alabilirim?

Temel olarak:

  1. Dosya yapısını kontrol ederseniz, bu duruma girmekten kaçınmaya çalışırdım.
  2. Java NIO.2'de, daha büyük ölçeklendirmeye izin vermek için bir yineleyici döndürmek için dizinler işlevini kullanabilirsiniz. Dizin akışı sınıfı, bir dizindeki girdileri yinelemek için kullanabileceğiniz bir nesnedir.

merhaba, cevap için teşekkürler. Ancak bir dizindeki tüm öğeleri yinelememe gerek yok. Alt dizini doğrudan dizinden listelemem gerekiyor. B'coz Çok sayıda dosyam var ve bir dizinde yalnızca birkaç alt dizinim var, bu yüzden isDirectory () 'yi kontrol etmek zaman alıcı. lütfen bana başka bir şekilde cevap verin.
Lokesh Paunikar

Yazımı güncelledim, özellikle soruyla ilgili Jon Skeet yorumuna bir göz atın. Ve Java NIO 2, bir dizin akışı döndüren dizinler işlevi için bir yineleyiciye sahip olduğundan NIO yanıtı.
Mohamed Mansour

Hangi Skeet yorumundan bahsediyorsunuz? Burada daha iyi performans gösteren cevap nedir?
Stealth Rabbi

107

Çok basit bir Java 8 çözümü:

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

Bir FileFilter kullanmaya eşdeğerdir (eski Java ile de çalışır):

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

4
::Bu durumda çift ​​kolon nasıl çalışır?
snickers10m

Başka hiçbir yanıtın FileFilter kullanmadığını fark ettim, bu yüzden eşdeğer sürümü yöntem referansları kullanmadan ekledim. Yöntem referansları hakkında daha fazla bilgi için, bu SO sorusuna veya bu makaleye bakın .
headsvk

bu alt dizinleri mi, yoksa doğrudan / sizin / yolunuz altındaki dizinleri mi alıyor?
amadain


14

@Mohamed Mansour neredeyse oradaydınız ... Kullandığınız "dir" argümanı aslında geçerli yoldur, bu nedenle her zaman doğruya dönecektir. Çocuğun bir alt dizin olup olmadığını görmek için o çocuğu test etmeniz gerekir.

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 ve NIO.2 kullanan bir çözümle ilgileniyorsanız, şu şekilde olabilir:

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

Merhaba, StackOverflow'a hoş geldiniz! Cevabınızı biraz detaylandırır mısınız? Örneğin kod parçacıklarınızın ilginç kısımlarını açıklamak veya daha fazla okumak için belgelere bağlantı vermek gibi mi?
Richard-Degenne

Tam Kanonik Yol ile bir File nesnesi sağladığı için bu doğru cevap olmalıdır. Bu eski olabilir ama şunu belirtmeye değer
Jero Dungog

3

Java.io.File işlevini kullanmak istiyorum,

2012'de (sorunun tarihi) evet, bugün değil. java.nioAPI, bu tür gereksinimler için tercih edilmelidir.

Bu kadar çok cevapla berbat, ama benim kullanacağım basit yol değil Files.walk().filter().collect().

Küresel olarak iki yaklaşım mümkündür:

1) Files.walk(Path start, )herhangi bir maxDepthsınırlama yoktur

2) Files.walk(Path start, int maxDepth, FileVisitOption... options)ayarlamaya izin verir.

Herhangi bir derinlik sınırlaması belirtmeden, şunları verir:

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

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

Ve eski nedenlerden dolayı, bir Listenizi almanız gerekiyorsa , toplamadan önce Filebir map(Path::toFile)işlem ekleyebilirsiniz :

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
}

Orada da Files.list(Path)muhtemelen aynı olan Files.walk(Path,1).
David L.

@David L Indeed Files.list(Path), klasörleri yinelemeli olarak yinelemek istemiyorsak adil bir alternatiftir. Klasörleri yinelemeli olarak yinelemek için walk()daha iyi uyuyor.
davidxxx

2

Java 7 ve NIO ile de ilgilenenler için, @ voo'nun yukarıdaki cevabına alternatif bir çözüm var . Biz kullanabilirsiniz deneyin-ile-kaynaklar bu aramaları Files.find()ve dizinleri filtrelemek için kullanılan bir lambda fonksiyonu.

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

Lambda işlevini değiştirerek dizinleri ada göre bile filtreleyebiliriz:

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

veya tarihe göre:

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


0

Bir başlangıç ​​dizini olarak verildiğinde String

  1. StringParametre olarak bir yol alan bir yöntem oluşturun . Yöntemde:
  2. Başlangıç ​​dizinine göre yeni bir File nesnesi oluşturun
  3. listFilesYöntemi kullanarak geçerli dizindeki bir dizi dosya alın
  4. Dosya dizisi üzerinde döngü yapın
    1. Dosya ise, döngüye devam edin
    2. Bir dizin ise, adı yazdırın ve bu yeni dizin yolunda tekrarlayın

merhaba, cevabınız için teşekkürler. Ancak bir dizindeki tüm öğeleri yinelememe gerek yok. Alt dizini doğrudan dizinden listelemem gerekiyor. B'coz Çok sayıda dosyam var ve bir dizinde yalnızca birkaç alt dizinim var, bu yüzden isDirectory () 'yi kontrol etmek zaman alıcı. lütfen bana başka bir şekilde cevap verin.
Lokesh Paunikar

0

İşte kodum için çözüm. İlk cevaptan biraz değişiklik yaptım . Bu, tüm klasörleri yalnızca istenen dizinde satır satır listeleyecektir:

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

JAVA 7 Files api'sini kullanabilirsiniz

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

Belirli bir değer istiyorsanız, verileri toplamadan önce istediğiniz değerle haritayı çağırabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.