Иногда требуется узнать размер директории на файловой системе. В Java это можно сделать несколькими способами — с помощью стандартного API и внешних библиотек.
Здесь мы рассмотрим различные способы узнать размер директории:
- Используя сторонню библиотеку Apache Commons IO (FileUtils.sizeOfDirectory)
- Используя стандартную библиотеку Java 8 (Files.walk)
- Используя стандартную библиотеку Java 7 (FileVisitor)
- Используя стандартную библиотеку Java 6
1. Размер директории с помощью Apache Commons IO
Это наиболее простой в использовании способ — достаточно воспользоваться одним методом из этой библиотеки. Но сначала её требуется подключить к проекту:
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.7</version> </dependency>
После этого, воспользуемся методом sizeOfDirectory:
FileUtils.sizeOfDirectory(new File("/home/alex/java-lessons.ru"));
В ответ вернётся размер директории в байтах:
2. Размер директории с помощью Files.walk (Java 8+)
Если вы не хотите подключать сторонние библиотеки, можно воспользоваться стандартным API. В Java 8 появился метод Files.walk, с помощью которого можно обойти все файлы в директории и подсчитать их размер:
Path path = Paths.get("/home/alex/java-lessons.ru"); long size = 0; try (Stream<Path> walk = Files.walk(path)) { size = walk .filter(Files::isRegularFile) .mapToLong(p -> { try { return Files.size(p); } catch (IOException e) { System.out.printf("Невозможно получить размер файла %s%n%s", p, e); return 0L; } }) .sum(); } catch (IOException e) { System.out.printf("Ошибка при подсчёте размера директории %s", e); } System.out.println(size);
3. Размер директории с помощью FileVisitor (Java 7+)
Если вы используете Java 7, вы можете воспользоваться стандартным FileVisitor:
Path path = Paths.get("/home/alex/java-lessons.ru"); AtomicLong size = new AtomicLong(0); try { Files.walkFileTree(path, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { // sum size of all visit file size.addAndGet(attrs.size()); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException e) throws IOException { System.out.printf("Невозможно получить размер файла %s%n%s", file, e); return FileVisitResult.CONTINUE; } }); } catch (IOException e) { System.out.printf("Ошибка при подсчёте размера директории %s", e); } System.out.println(size);
Здесь принцип тот же, что и в примере с Files.walk — приходится обходить все файлы в директории и подсчитывать их размер.
3. Размер директории с помощью FileVisitor (Java 6+)
Если же вы располагает Java 6, для подсчёта размера всех вложенных файлов придётся рекурсивно итерироваться по директориям:
public static long getDirectorySizeJava6(File dir) { long length = 0; File[] files = dir.listFiles(); if (files != null) { for (File file : files) { if (file.isFile()) length += file.length(); else length += getDirectorySizeJava6(file); } } return length; }
Исходный код
import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Stream; public class GetFolderSize { public static void main(String[] args) { System.out.println(getDirectorySizeJava8("/home/alex/java-lessons.ru")); } public static long getDirectorySizeApache(String path) { return FileUtils.sizeOfDirectory(new File(path)); } public static long getDirectorySizeJava8(String s) { Path path = Paths.get(s); long size = 0; try (Stream<Path> walk = Files.walk(path)) { size = walk .filter(Files::isRegularFile) .mapToLong(p -> { try { return Files.size(p); } catch (IOException e) { System.out.printf("Невозможно получить размер файла %s%n%s", p, e); return 0L; } }) .sum(); } catch (IOException e) { System.out.printf("Ошибка при подсчёте размера директории %s", e); } return size; } public static long getDirectorySizeJava7(String s) { Path path = Paths.get(s); AtomicLong size = new AtomicLong(0); try { Files.walkFileTree(path, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { // sum size of all visit file size.addAndGet(attrs.size()); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException e) throws IOException { System.out.printf("Невозможно получить размер файла %s%n%s", file, e); return FileVisitResult.CONTINUE; } }); } catch (IOException e) { System.out.printf("Ошибка при подсчёте размера директории %s", e); } return size.get(); } public static long getDirectorySizeJava6(File dir) { long length = 0; File[] files = dir.listFiles(); if (files != null) { for (File file : files) { if (file.isFile()) length += file.length(); else length += getDirectorySizeJava6(file); } } return length; } }
Заключение
Для подсчёта размера директории подходят несколько способов — с подключением сторонних библиотек и с использованием стандартного API в Java. Сторонние библиотеки обычно предоставляют удобный в использовании метод, который скрывает весь шаблонный код по обходу дерева файлов. А со стандартным API придётся повозиться, но зато у вас в проекте не будет ещё одной зависимости в виде сторонней библиотеки.