Перейти к основному содержимому

Java — размер каталога

· 4 мин. чтения

1. Обзор

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

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

2. С Явой

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

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 путем применения функции длины к каждому элементу, после чего мы можем просуммировать и получить окончательный результат.

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<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, поэтому его легко импортировать и запускать как есть.