Java - Размер каталога

Java - Размер каталога

1. обзор

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

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

2. С Java

Начнем с простого примера расчета размера папки -using the sum of its contents:

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 to get the folder size. В следующем примере мы используем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() {
        @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, stream operations and lambdas. В следующем примере мы используем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 путем применения функцииlength в каждом элементе - после чего мы можемsum и получить окончательный результат.

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. В следующем примере мы используемFiles.fileTreeTraverser() для обхода всех файлов в папке, чтобы суммировать их размер:

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

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

    Iterable files = Files.fileTreeTraverser()
          .breadthFirstTraversal(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 для расчета размера каталога в файловой системе.

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