如何遍历Java中的目录中的文件?

时间:2010-07-01 01:02:54

标签: java

我需要获取目录中所有文件的列表,包括所有子目录中的文件。使用Java完成目录迭代的标准方法是什么?

10 个答案:

答案 0 :(得分:187)

您可以使用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());
        }
    }
}

请注意,当树比JVM的堆栈更深时,这对StackOverflowError敏感。您可能希望使用迭代方法或tail-recursion,但这是另一个主题;)

答案 1 :(得分:77)

如果您使用的是Java 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();
    }
  }

}

如果您使用的是Java 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();
    }
  }

}

答案 2 :(得分:27)

查看Apache Commons中的FileUtils类 - 特别是iterateFiles

  

允许迭代给定目录(以及可选的子目录)中的文件。

答案 3 :(得分:7)

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

如果您不想要子目录中的文件,请使用false。

答案 4 :(得分:7)

对于Java 7+,还有https://docs.oracle.com/javase/7/docs/api/java/nio/file/DirectoryStream.html

取自Javadoc的示例:

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

答案 5 :(得分:3)

这是一棵树,所以递归是你的朋友:从父目录开始并调用方法来获取子文件数组。遍历子数组。如果当前值是目录,则将其传递给方法的递归调用。如果没有,请适当处理叶文件。

答案 6 :(得分:2)

如上所述,这是一个递归问题。特别是,您可能需要查看

listFiles() 

在java文件API here中。它返回目录中所有文件的数组。与

一起使用
isDirectory()

看你是否需要进一步提升是一个好的开始。

答案 7 :(得分:0)

要添加@msandiford答案,因为大多数时候走路文件树你可能想要执行一个函数作为目录或访问任何特定文件。如果你不愿意使用流。可以实现以下覆盖方法

<ScrollView horizontal={true}>

                    <View style={{
                        height: 9,
                    }}>
                        {/*buffer between items*/}
                    </View>

                    <View 
                        style={{flexDirection: 'row',
                        width: width-9,
                        height: 50,
                        top: 163,
                        alignContent: 'center',
                        alignItems: 'center',
                        //justifyContent: 'flex-wrap',
                        flexWrap: 'wrap'
                        }}
                    >

                        {/*card 1*/}
                        <Card
                            onPress={() => navigate('General')}
                            source={require('../resources/icons/information.png')}
                            text={'General Info'}
                        >
                        </Card>

                        {/*card 2*/}
                        <Card
                            onPress={() => navigate('Grades')}
                            source={require('../resources/icons/information.png')}
                            text={'Gradebook'}
                        >
                        </Card>

                        {/*card 3*/}
                        <Card
                            onPress={() => navigate('Grades')}
                            source={require('../resources/icons/information.png')}
                            text={'Lunch Menu'}
                        >
                        </Card>

                        {/*card 4*/}
                        <Card
                            onPress={() => navigate('BellSchedule')}
                            source={require('../resources/icons/information.png')}
                            text={'Bell Schedules'}
                        >
                        </Card>

                        {/*card 5*/}
                        <Card
                            onPress={() => navigate('About')}
                            source={require('../resources/icons/information.png')}
                            text={'About'}
                        >
                        </Card>

                    </View>

                </ScrollView>

答案 8 :(得分:0)

您还可以滥用File.list(FilenameFilter)(和变体)进行文件遍历。简短的代码,可以在早期的Java版本中使用,例如:

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

答案 9 :(得分:0)

我喜欢使用 Optional streams 来获得一个清晰明确的解决方案, 我使用下面的代码遍历目录。以下情况由代码处理:

  1. 处理目录为空的情况
  2. 懒惰

但是正如其他人所提到的,如果您有巨大的文件夹,您仍然需要注意outOfMemory

    File directoryFile = new File("put your path here");
    Stream<File> files = Optional.ofNullable(directoryFile// directoryFile
                                                          .listFiles(File::isDirectory)) // filter only directories(change with null if you don't need to filter)
                                 .stream()
                                 .flatMap(Arrays::stream);// flatmap from Stream<File[]> to Stream<File>