Java로 파일을 재귀 적으로 나열
Java의 디렉토리 아래에있는 모든 파일을 재귀 적으로 나열하려면 어떻게합니까? 프레임 워크가 유틸리티를 제공합니까?
나는 많은 해키 구현을 보았습니다. 그러나 프레임 워크 나 nio 에서 아무도
Java 8은 트리에서 모든 파일을 처리 할 수있는 멋진 스트림을 제공합니다.
Files.walk(Paths.get(path))
.filter(Files::isRegularFile)
.forEach(System.out::println);
이것은 파일을 순회하는 자연스러운 방법을 제공합니다. 스트림이므로 제한, 그룹화, 매핑, 조기 종료 등과 같은 결과에 대해 멋진 스트림 작업을 모두 수행 할 수 있습니다.
UPDATE : 나는 또한이 점을 지적 할 수 Files.find 소요 BiPredicate 당신은 파일 특성을 확인해야하는 경우 더 효율적이 될 수 있습니다.
Files.find(Paths.get(path),
Integer.MAX_VALUE,
(filePath, fileAttr) -> fileAttr.isRegularFile())
.forEach(System.out::println);
JavaDoc은이 방법이 Files.walk 보다 효율적일 수는 없지만 , 필터 내에서 파일 속성을 검색하는 경우 성능의 차이를 관찰 할 수 없다는 점에 유의 하십시오. 결국, 속성을 필터링 해야하는 경우 Files.find를 사용 하고 그렇지 않으면 Files.walk를 사용 하십시오 . 주로 과부하가 있고 더 편리합니다.
테스트 : 요청에 따라 많은 답변의 성능 비교를 제공했습니다. 결과 및 테스트 사례가 포함 된 Github 프로젝트를 확인하십시오 .
Fileutils의는 이 iterateFiles
와 listFiles
방법. 그들에게 시도하십시오. ( commons-io에서 )
편집 : 여기 에서 다양한 접근 방식의 벤치 마크를 확인할 수 있습니다 . commons-io 접근 방식이 느리므로 여기 에서 더 빠른 것을 선택 하십시오 (중요한 경우)
// 실행할 준비가되었습니다
import java.io.File;
public class Filewalker {
public void walk( String path ) {
File root = new File( path );
File[] list = root.listFiles();
if (list == null) return;
for ( File f : list ) {
if ( f.isDirectory() ) {
walk( f.getAbsolutePath() );
System.out.println( "Dir:" + f.getAbsoluteFile() );
}
else {
System.out.println( "File:" + f.getAbsoluteFile() );
}
}
}
public static void main(String[] args) {
Filewalker fw = new Filewalker();
fw.walk("c:\\" );
}
}
자바 7
것은
이 Files.walkFileTree를 :
시작점과 파일 방문자를 제공하면 파일 트리에서 파일을 탐색 할 때 파일 방문자에 대해 다양한 메소드를 호출합니다. 사람들이 재귀 복사, 재귀 이동, 재귀 삭제 또는 재귀 작업을 개발하는 경우 각 파일에 대해 권한을 설정하거나 다른 작업을 수행하는 경우이를 사용할 것을 기대합니다.
이 질문에 대한 전체 Oracle 튜토리얼이 있습니다.
외부 라이브러리가 필요하지 않습니다.
통화 후 원하는 작업을 수행 할 수 있도록 컬렉션을 반환합니다.
public static Collection<File> listFileTree(File dir) {
Set<File> fileTree = new HashSet<File>();
if(dir==null||dir.listFiles()==null){
return fileTree;
}
for (File entry : dir.listFiles()) {
if (entry.isFile()) fileTree.add(entry);
else fileTree.addAll(listFileTree(entry));
}
return fileTree;
}
나는 다음과 같이 갈 것이다.
public void list(File file) {
System.out.println(file.getName());
File[] children = file.listFiles();
for (File child : children) {
list(child);
}
}
System.out.println은 파일로 무언가를 수행하기 위해 나타납니다. 일반 파일에는 단순히 자식이 없기 때문에 파일과 디렉토리를 구분할 필요가 없습니다.
이런 종류의 간단한 트래버스에는 재귀보다 큐를 사용하는 것이 좋습니다.
List<File> allFiles = new ArrayList<File>();
Queue<File> dirs = new LinkedList<File>();
dirs.add(new File("/start/dir/"));
while (!dirs.isEmpty()) {
for (File f : dirs.poll().listFiles()) {
if (f.isDirectory()) {
dirs.add(f);
} else if (f.isFile()) {
allFiles.add(f);
}
}
}
간단한 재귀를 사용하여 직접 작성하십시오.
public List<File> addFiles(List<File> files, File dir)
{
if (files == null)
files = new LinkedList<File>();
if (!dir.isDirectory())
{
files.add(dir);
return files;
}
for (File file : dir.listFiles())
addFiles(files, file);
return files;
}
Java 7에서는 다음 클래스를 사용할 수 있습니다.
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
public class MyFileIterator extends SimpleFileVisitor<Path>
{
public MyFileIterator(String path) throws Exception
{
Files.walkFileTree(Paths.get(path), this);
}
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attributes) throws IOException
{
System.out.println("File: " + file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attributes) throws IOException
{
System.out.println("Dir: " + dir);
return FileVisitResult.CONTINUE;
}
}
나는 이것이 일을해야한다고 생각한다.
File dir = new File(dirname);
String[] files = dir.list();
이렇게하면 파일과 디렉토리가 있습니다. 이제 재귀를 사용하고 dirs에 대해 동일한 작업을 수행하십시오 ( File
class has isDirectory()
method).
이 코드는 실행할 준비가되었습니다
public static void main(String... args) {
File[] files = new File("D:/").listFiles();
if (files != null)
getFiles(files);
}
public static void getFiles(File[] files) {
for (File file : files) {
if (file.isDirectory()) {
getFiles(file.listFiles());
} else {
System.out.println("File: " + file);
}
}
}
Java 8에서는 이제 파일 유틸리티를 사용하여 파일 트리를 걸을 수 있습니다. 매우 간단합니다.
Files.walk(root.toPath())
.filter(path -> !Files.isDirectory(path))
.forEach(path -> System.out.println(path));
재귀 순회 외에도 방문자 기반 접근 방식을 사용할 수도 있습니다.
아래 코드는 순회에 방문자 기반 접근 방식을 사용합니다. 아래 코드는 순회에 대한 루트 디렉토리 일 것으로 예상됩니다.
public interface Visitor {
void visit(DirElement d);
void visit(FileElement f);
}
public abstract class Element {
protected File rootPath;
abstract void accept(Visitor v);
@Override
public String toString() {
return rootPath.getAbsolutePath();
}
}
public class FileElement extends Element {
FileElement(final String path) {
rootPath = new File(path);
}
@Override
void accept(final Visitor v) {
v.visit(this);
}
}
public class DirElement extends Element implements Iterable<Element> {
private final List<Element> elemList;
DirElement(final String path) {
elemList = new ArrayList<Element>();
rootPath = new File(path);
for (File f : rootPath.listFiles()) {
if (f.isDirectory()) {
elemList.add(new DirElement(f.getAbsolutePath()));
} else if (f.isFile()) {
elemList.add(new FileElement(f.getAbsolutePath()));
}
}
}
@Override
void accept(final Visitor v) {
v.visit(this);
}
public Iterator<Element> iterator() {
return elemList.iterator();
}
}
public class ElementWalker {
private final String rootDir;
ElementWalker(final String dir) {
rootDir = dir;
}
private void traverse() {
Element d = new DirElement(rootDir);
d.accept(new Walker());
}
public static void main(final String[] args) {
ElementWalker t = new ElementWalker("C:\\temp");
t.traverse();
}
private class Walker implements Visitor {
public void visit(final DirElement d) {
System.out.println(d);
for(Element e:d) {
e.accept(this);
}
}
public void visit(final FileElement f) {
System.out.println(f);
}
}
}
아래 코드를 사용하여 특정 폴더 또는 디렉토리의 파일 목록을 재귀 적으로 얻을 수 있습니다.
public static void main(String args[]) {
recusiveList("D:");
}
public static void recursiveList(String path) {
File f = new File(path);
File[] fl = f.listFiles();
for (int i = 0; i < fl.length; i++) {
if (fl[i].isDirectory() && !fl[i].isHidden()) {
System.out.println(fl[i].getAbsolutePath());
recusiveList(fl[i].getAbsolutePath());
} else {
System.out.println(fl[i].getName());
}
}
}
단일 목록이있는 비 재귀 BFS (특히 예제는 * .eml 파일 검색) :
final FileFilter filter = new FileFilter() {
@Override
public boolean accept(File file) {
return file.isDirectory() || file.getName().endsWith(".eml");
}
};
// BFS recursive search
List<File> queue = new LinkedList<File>();
queue.addAll(Arrays.asList(dir.listFiles(filter)));
for (ListIterator<File> itr = queue.listIterator(); itr.hasNext();) {
File file = itr.next();
if (file.isDirectory()) {
itr.remove();
for (File f: file.listFiles(filter)) itr.add(f);
}
}
내 버전 (물론 Java 8;-에서 내장 워크를 사용할 수 있음) :
public static List<File> findFilesIn(File rootDir, Predicate<File> predicate) {
ArrayList<File> collected = new ArrayList<>();
walk(rootDir, predicate, collected);
return collected;
}
private static void walk(File dir, Predicate<File> filterFunction, List<File> collected) {
Stream.of(listOnlyWhenDirectory(dir))
.forEach(file -> walk(file, filterFunction, addAndReturn(collected, file, filterFunction)));
}
private static File[] listOnlyWhenDirectory(File dir) {
return dir.isDirectory() ? dir.listFiles() : new File[]{};
}
private static List<File> addAndReturn(List<File> files, File toAdd, Predicate<File> filterFunction) {
if (filterFunction.test(toAdd)) {
files.add(toAdd);
}
return files;
}
다음을 사용하여 간단하지만 완벽하게 작동하는 솔루션입니다 recursion
.
public static List<Path> listFiles(String rootDirectory)
{
List<Path> files = new ArrayList<>();
listFiles(rootDirectory, files);
return files;
}
private static void listFiles(String path, List<Path> collectedFiles)
{
File root = new File(path);
File[] files = root.listFiles();
if (files == null)
{
return;
}
for (File file : files)
{
if (file.isDirectory())
{
listFiles(file.getAbsolutePath(), collectedFiles);
} else
{
collectedFiles.add(file.toPath());
}
}
}
private void fillFilesRecursively(File file, List<File> resultFiles) {
if (file.isFile()) {
resultFiles.add(file);
} else {
for (File child : file.listFiles()) {
fillFilesRecursively(child, resultFiles);
}
}
}
나는 모든 파일 / 파일 이름을 재귀 적으로 인쇄하기 위해 이것을 생각해 냈습니다.
private static void printAllFiles(String filePath,File folder) {
if(filePath==null) {
return;
}
File[] files = folder.listFiles();
for(File element : files) {
if(element.isDirectory()) {
printAllFiles(filePath,element);
} else {
System.out.println(" FileName "+ element.getName());
}
}
}
예제는 java.nio의 Files.find ()를 사용하여 디렉토리 재귀 검색 서브 디렉토리에서 * .csv 파일을 출력합니다.
String path = "C:/Daten/ibiss/ferret/";
logger.debug("Path:" + path);
try (Stream<Path> fileList = Files.find(Paths.get(path), Integer.MAX_VALUE,
(filePath, fileAttr) -> fileAttr.isRegularFile() && filePath.toString().endsWith("csv"))) {
List<String> someThingNew = fileList.sorted().map(String::valueOf).collect(Collectors.toList());
for (String t : someThingNew) {
t.toString();
logger.debug("Filename:" + t);
}
}
이 예제를 게시하면 Bryan이 제공 한 # 1 예제에서 filename 매개 변수를 전달하는 방법을 이해하는 데 어려움이 있었으므로 foreach on stream-result-
도움이 되었기를 바랍니다.
스태커 답변을 기반으로합니다. 다음은 외부 라이브러리없이 JSP에서 작동하는 솔루션이므로 서버의 거의 모든 곳에 배치 할 수 있습니다.
<!DOCTYPE html>
<%@ page session="false" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%!
public List<String> files = new ArrayList<String>();
/**
Fills files array with all sub-files.
*/
public void walk( File root ) {
File[] list = root.listFiles();
if (list == null) return;
for ( File f : list ) {
if ( f.isDirectory() ) {
walk( f );
}
else {
files.add(f.getAbsolutePath());
}
}
}
%>
<%
files.clear();
File jsp = new File(request.getRealPath(request.getServletPath()));
File dir = jsp.getParentFile();
walk(dir);
String prefixPath = dir.getAbsolutePath() + "/";
%>
그런 다음 다음과 같은 작업을 수행하십시오.
<ul>
<% for (String file : files) { %>
<% if (file.matches(".+\\.(apk|ipa|mobileprovision)")) { %>
<li><%=file.replace(prefixPath, "")%></li>
<% } %>
<% } %>
</ul>
참고 URL : https://stackoverflow.com/questions/2056221/recursively-list-files-in-java
'IT story' 카테고리의 다른 글
vim에서 C 코드를 자동 서식 / 인 덴트하려면 어떻게해야합니까? (0) | 2020.04.11 |
---|---|
ViewPager에서 조각 검색 (0) | 2020.04.11 |
div 높이를 배경 크기로 자동 조정하는 방법은 무엇입니까? (0) | 2020.04.11 |
장치를 컴파일 할 때 Apple Mach-O 링커 오류 (0) | 2020.04.11 |
해시에서 문자열을 기호로 변환하는 가장 좋은 방법 (0) | 2020.04.11 |