developer tip

폴더 또는 파일 크기 가져 오기

optionbox 2020. 8. 21. 07:35
반응형

폴더 또는 파일 크기 가져 오기


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 탐색기 자체와 동일한 크기 정보를 제공합니다.


Java 8 NIO API 를 사용 하려면 다음 프로그램이 위치하는 디렉토리의 크기 (바이트)를 인쇄합니다.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class PathSize {

    public static void main(String[] args) {
        Path path = Paths.get(".");
        long size = calculateSize(path);
        System.out.println(size);
    }

    /**
     * Returns the size, in bytes, of the specified <tt>path</tt>. If the given
     * path is a regular file, trivially its size is returned. Else the path is
     * a directory and its contents are recursively explored, returning the
     * total sum of all files within the directory.
     * <p>
     * If an I/O exception occurs, it is suppressed within this method and
     * <tt>0</tt> is returned as the size of the specified <tt>path</tt>.
     * 
     * @param path path whose size is to be returned
     * @return size of the specified path
     */
    public static long calculateSize(Path path) {
        try {
            if (Files.isRegularFile(path)) {
                return Files.size(path);
            }

            return Files.list(path).mapToLong(PathSize::calculateSize).sum();
        } catch (IOException e) {
            return 0L;
        }
    }

}

calculateSize방법은 Path개체에 보편적 이므로 파일에도 적용됩니다. 참고 파일이나 디렉토리에 액세스 할 수없는 경우,이 경우에는 반환 된 크기 경로 객체가 될 것입니다 0.


File.length()( Javadoc ).

이것은 디렉토리에서 작동하지 않거나 작동이 보장되지 않습니다.

디렉토리의 경우 무엇을 원하십니까? 모든 파일을 아래의이 전체 크기의 경우, 반복적으로 사용하여 아이들을 걸을 수 File.list()File.isDirectory()그들의 크기를 요약.


File객체는이 length방법을 :

f = new File("your/file/name");
f.length();

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

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

  • AndroidJava에서 작동
  • 폴더와 파일 모두에서 작동
  • 필요한 모든 곳에서 널 포인터를 확인합니다.
  • 바로 가기라고도하는 심볼릭 링크 무시
  • 생산 준비 완료!

소스 코드:

   public long fileSize(File root) {
        if(root == null){
            return 0;
        }
        if(root.isFile()){
            return root.length();
        }
        try {
            if(isSymlink(root)){
                return 0;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return 0;
        }

        long length = 0;
        File[] files = root.listFiles();
        if(files == null){
            return 0;
        }
        for (File file : files) {
            length += fileSize(file);
        }

        return length;
    }

    private static boolean isSymlink(File file) throws IOException {
        File canon;
        if (file.getParent() == null) {
            canon = file;
        } else {
            File canonDir = file.getParentFile().getCanonicalFile();
            canon = new File(canonDir, file.getName());
        }
        return !canon.getCanonicalFile().equals(canon.getAbsoluteFile());
    }

public long folderSize (String directory)
    {
        File curDir = new File(directory);
        long length = 0;
        for(File f : curDir.listFiles())
        {
            if(f.isDirectory())
            {               
                 for ( File child : f.listFiles()) 
                 {
                     length = length + child.length();
                 }

                System.out.println("Directory: " + f.getName() + " " + length + "kb");
            }
            else
            {
                length = f.length();
                System.out.println("File: " + f.getName() + " " + length + "kb");
            }
            length = 0;
        }
        return length;
    }

여기 StackOverflow에서 제안 된 다양한 솔루션을 많이 연구하고 조사한 후. 마침내 내 자신의 솔루션을 작성하기로 결정했습니다. 내 목적은 API가 폴더 크기를 가져올 수없는 경우 충돌을 원하지 않기 때문에 던지지 않는 메커니즘을 갖는 것입니다. 이 방법은 다중 스레드 시나리오에 적합하지 않습니다.

우선 파일 시스템 트리를 탐색하면서 유효한 디렉토리를 확인하고 싶습니다.

private static boolean isValidDir(File dir){
    if (dir != null && dir.exists() && dir.isDirectory()){
        return true;
    }else{
        return false;
    }
}

Second I do not want my recursive call to go into symlinks (softlinks) and include the size in total aggregate.

public static boolean isSymlink(File file) throws IOException {
    File canon;
    if (file.getParent() == null) {
        canon = file;
    } else {
        canon = new File(file.getParentFile().getCanonicalFile(),
                file.getName());
    }
    return !canon.getCanonicalFile().equals(canon.getAbsoluteFile());
}

Finally my recursion based implementation to fetch the size of the specified directory. Notice the null check for dir.listFiles(). According to javadoc there is a possibility that this method can return null.

public static long getDirSize(File dir){
    if (!isValidDir(dir))
        return 0L;
    File[] files = dir.listFiles();
    //Guard for null pointer exception on files
    if (files == null){
        return 0L;
    }else{
        long size = 0L;
        for(File file : files){
            if (file.isFile()){
                size += file.length();
            }else{
                try{
                    if (!isSymlink(file)) size += getDirSize(file);
                }catch (IOException ioe){
                    //digest exception
                }
            }
        }
        return size;
    }
}

Some cream on the cake, the API to get the size of the list Files (might be all of files and folder under root).

public static long getDirSize(List<File> files){
    long size = 0L;
    for(File file : files){
        if (file.isDirectory()){
            size += getDirSize(file);
        } else {
            size += file.length();
        }
    }
    return size;
}

in linux if you want to sort directories then du -hs * | sort -h


for windows, using java.io this reccursive function is useful.

    public static long folderSize(File directory) {
    long length = 0;

    if (directory.isFile())
         length += directory.length();
    else{
        for (File file : directory.listFiles()) {
             if (file.isFile())
                 length += file.length();
             else
                 length += folderSize(file);
        }
    }

    return length;
}

This is tested and working properly on my end.

참고URL : https://stackoverflow.com/questions/2149785/get-size-of-folder-or-file

반응형