[java] 폴더 또는 파일 크기 가져 오기

Java에서 폴더 또는 파일의 크기를 검색하려면 어떻게해야합니까?



답변

java.io.File file = new java.io.File("myfile.txt");
file.length();

파일의 길이를 바이트 단위로 반환하거나 0파일이없는 경우 반환 합니다. 폴더 크기를 가져 오는 기본 제공 방법은 없습니다. 디렉토리 listFiles()를 나타내는 파일 객체 의 방법을 사용하여 디렉토리 트리를 재귀 적으로 살펴보고 직접 디렉토리 크기를 축적해야합니다.

public static long folderSize(File directory) {
    long length = 0;
    for (File file : directory.listFiles()) {
        if (file.isFile())
            length += file.length();
        else
            length += folderSize(file);
    }
    return length;
}

경고 :이 방법은 생산 용으로 충분히 견고하지 않습니다. directory.listFiles()반환 null되어 NullPointerException. 또한 심볼릭 링크를 고려하지 않으며 다른 오류 모드가있을 수 있습니다. 이 방법 사용 .


답변

java-7 nio api를 사용하면 폴더 크기를 훨씬 빠르게 계산할 수 있습니다.

다음은 강력하고 예외를 발생시키지 않는 실행할 준비가 된 예제입니다. 입력 할 수 없거나 통과하는 데 문제가있는 디렉터리를 기록합니다. Symlink는 무시되며 디렉토리를 동시에 수정해도 필요 이상으로 문제가 발생하지 않습니다.

/**
 * Attempts to calculate the size of a file or directory.
 *
 * <p>
 * Since the operation is non-atomic, the returned value may be inaccurate.
 * However, this method is quick and does its best.
 */
public static long size(Path path) {

    final AtomicLong size = new AtomicLong(0);

    try {
        Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {

                size.addAndGet(attrs.size());
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) {

                System.out.println("skipped: " + file + " (" + exc + ")");
                // Skip folders that can't be traversed
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) {

                if (exc != null)
                    System.out.println("had trouble traversing: " + dir + " (" + exc + ")");
                // Ignore errors traversing a folder
                return FileVisitResult.CONTINUE;
            }
        });
    } catch (IOException e) {
        throw new AssertionError("walkFileTree will not throw IOException if the FileVisitor does not");
    }

    return size.get();
}


답변

commons-ioFileUtils#sizeOfDirectory(File) 에서 필요합니다 .

비 디렉토리가 전달되면 메소드에서 예외가 발생하므로 파일이 디렉토리인지 수동으로 확인해야합니다.

경고 :이 메소드 (commons-io 2.4 기준)에는 버그 IllegalArgumentException가 있으며 디렉토리가 동시에 수정되면 발생할 수 있습니다 .


답변

Java 8에서

long size = Files.walk(path).mapToLong( p -> p.toFile().length() ).sum();

사용하는 것이 더 좋을 것입니다 Files::size지도 단계에서 좋지만 확인 된 예외가 발생합니다.

업데이트 :
일부 파일 / 폴더에 액세스 할 수없는 경우 예외가 발생할 수 있음을 알고 있어야합니다. 이 질문Guava를 사용하는 다른 솔루션을 참조하십시오 .


답변

public static long getFolderSize(File dir) {
    long size = 0;
    for (File file : dir.listFiles()) {
        if (file.isFile()) {
            System.out.println(file.getName() + " " + file.length());
            size += file.length();
        }
        else
            size += getFolderSize(file);
    }
    return size;
}


답변

를 들어 자바 팔 이 그것을 할 수있는 하나의 올바른 방법은 다음과 같습니다

Files.walk(new File("D:/temp").toPath())
                .map(f -> f.toFile())
                .filter(f -> f.isFile())
                .mapToLong(f -> f.length()).sum()

모든 디렉터리를 필터링하는 것이 중요 합니다. 길이 방법이 디렉터리에 대해 0이 될 수있는 것은 아니기 때문입니다.

적어도이 코드는 Windows 탐색기 자체와 동일한 크기 정보를 제공합니다.


답변

일반적인 파일의 크기를 얻는 가장 좋은 방법은 다음과 같습니다 (디렉토리 및 비 디렉토리에서 작동).

public static long getSize(File file) {
    long size;
    if (file.isDirectory()) {
        size = 0;
        for (File child : file.listFiles()) {
            size += getSize(child);
        }
    } else {
        size = file.length();
    }
    return size;
}

편집 : 이것은 아마도 시간이 많이 걸리는 작업이 될 것입니다. UI 스레드에서 실행하지 마십시오.

또한 여기 ( https://stackoverflow.com/a/5599842/1696171 에서 가져옴 )는 반환 된 long에서 사용자가 읽을 수있는 문자열을 얻는 좋은 방법입니다.

public static String getReadableSize(long size) {
    if(size <= 0) return "0";
    final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" };
    int digitGroups = (int) (Math.log10(size)/Math.log10(1024));
    return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups))
            + " " + units[digitGroups];
}