«1. Обзор

В этом руководстве мы узнаем, как получить размер папки в Java, используя Java 6, 7 и новую Java 8, а также Guava и Apache Common IO.

Наконец, мы также получим удобочитаемое представление размера каталога.

2. С Java

Начнем с простого примера вычисления размера папки – используя сумму ее содержимого:

private long getFolderSize(File folder) {
    long length = 0;
    File[] files = folder.listFiles();

    int count = files.length;

    for (int i = 0; i < count; i++) {
        if (files[i].isFile()) {
            length += files[i].length();
        }
        else {
            length += getFolderSize(files[i]);
        }
    }
    return length;
}

Мы можем протестировать наш метод getFolderSize(), как в следующий пример:

@Test
public void whenGetFolderSizeRecursive_thenCorrect() {
    long expectedSize = 12607;

    File folder = new File("src/test/resources");
    long size = getFolderSize(folder);

    assertEquals(expectedSize, size);
}

Примечание: listFiles() используется для отображения содержимого данной папки.

3. С Java 7

Далее — давайте посмотрим, как использовать Java 7 для получения размера папки. В следующем примере мы используем Files.walkFileTree() для обхода всех файлов в папке и суммирования их размеров:

@Test
public void whenGetFolderSizeUsingJava7_thenCorrect() throws IOException {
    long expectedSize = 12607;

    AtomicLong size = new AtomicLong(0);
    Path folder = Paths.get("src/test/resources");

    Files.walkFileTree(folder, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 
          throws IOException {
            size.addAndGet(attrs.size());
            return FileVisitResult.CONTINUE;
        }
    });

    assertEquals(expectedSize, size.longValue());
}

Обратите внимание, как здесь мы используем возможности обхода дерева файловой системы и используем функцию посетителя. шаблон, чтобы помочь нам посетить и рассчитать размеры каждого файла и подпапки.

4. С Java 8

Теперь давайте посмотрим, как получить размер папки с помощью Java 8, потоковых операций и лямбда-выражений. В следующем примере мы используем Files.walk() для обхода всех файлов в папке, чтобы суммировать их размер:

@Test
public void whenGetFolderSizeUsingJava8_thenCorrect() throws IOException {
    long expectedSize = 12607;

    Path folder = Paths.get("src/test/resources");
    long size = Files.walk(folder)
      .filter(p -> p.toFile().isFile())
      .mapToLong(p -> p.toFile().length())
      .sum();

    assertEquals(expectedSize, size);
}

Примечание: mapToLong() используется для создания LongStream путем применения функции длины в каждом element — после чего мы можем просуммировать и получить окончательный результат.

5. С Apache Commons IO

Далее — давайте посмотрим, как получить размер папки с помощью Apache Commons IO. В следующем примере мы просто используем FileUtils.sizeOfDirectory(), чтобы получить размер папки:

@Test
public void whenGetFolderSizeUsingApacheCommonsIO_thenCorrect() {
    long expectedSize = 12607;

    File folder = new File("src/test/resources");
    long size = FileUtils.sizeOfDirectory(folder);

    assertEquals(expectedSize, size);
}

Обратите внимание, что этот точный служебный метод реализует под капотом простое решение Java 6.

Также обратите внимание, что библиотека также предоставляет метод FileUtils.sizeOfDirectoryAsBigInteger(), который лучше работает с каталогами с ограниченным доступом.

6. С помощью Guava

Теперь давайте посмотрим, как рассчитать размер папки с помощью Guava. В следующем примере мы используем Files.fileTreeTraverser() для обхода всех файлов в папке и суммирования их размера:

@Test public void whenGetFolderSizeUsingGuava_thenCorrect() { 
    long expectedSize = 12607; 
    File folder = new File("src/test/resources"); 
   
    Iterable<File> files = Files.fileTraverser().breadthFirst(folder);
    long size = StreamSupport.stream(files.spliterator(), false) .filter(f -> f.isFile()) 
      .mapToLong(File::length).sum(); 
   
    assertEquals(expectedSize, size); 
}

7. Удобочитаемый размер

Наконец, давайте посмотрим, как получить более удобочитаемое представление размера папки, а не только размер в байтах:

@Test
public void whenGetReadableSize_thenCorrect() {
    File folder = new File("src/test/resources");
    long size = getFolderSize(folder);

    String[] units = new String[] { "B", "KB", "MB", "GB", "TB" };
    int unitIndex = (int) (Math.log10(size) / 3);
    double unitValue = 1 << (unitIndex * 10);

    String readableSize = new DecimalFormat("#,##0.#")
                                .format(size / unitValue) + " " 
                                + units[unitIndex];
    assertEquals("12.3 KB", readableSize);
}

Примечание. Мы использовали DecimalFormat(“#,##0,#” ) для округления результата до одного десятичного знака. место.

8. Примечания

Вот несколько замечаний по расчету размера папки:

    И Files.walk(), и Files.walkFileTree() вызовут исключение SecurityException, если менеджер безопасности откажет в доступе к исходному файлу. Бесконечный цикл может возникнуть, если папка содержит символические ссылки.

9. Заключение

В этом кратком руководстве мы проиллюстрировали примеры использования различных версий Java, Apache Commons IO и Guava для расчета размера каталога в файловой системе.

Реализацию этих примеров можно найти в проекте GitHub — это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.