Java - Tamanho do Diretório

Java - Tamanho do Diretório

1. Visão geral

Neste tutorial - aprenderemos como obter osize of a folder in Java - usando Java 6, 7 e o novo Java 8, bem como Guava e Apache Common IO.

Finalmente - também obteremos uma representação legível por humanos do tamanho do diretório.

2. Com Java

Vamos começar com um exemplo simples de cálculo do tamanho de uma pasta -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;
}

Podemos testar nosso métodogetFolderSize() como no exemplo a seguir:

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

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

    assertEquals(expectedSize, size);
}

Nota:listFiles() é usado para listar o conteúdo de uma determinada pasta.

3. Com Java 7

A seguir - vamos ver como usarJava 7 to get the folder size. No exemplo a seguir - usamosFiles.walkFileTree() para percorrer todos os arquivos na pasta e somar seus tamanhos:

@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());
}

Observe como estamos aproveitando os recursos de travessia da árvore do sistema de arquivos aqui e fazendo uso do padrão de visitante para nos ajudar a visitar e calcular os tamanhos de cada arquivo e subpasta.

4. Com Java 8

Agora - vamos ver como obter o tamanho da pasta usandoJava 8, stream operations and lambdas. No exemplo a seguir - usamosFiles.walk() para percorrer todos os arquivos na pasta e somar seus tamanhos:

@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);
}

Nota:mapToLong() é usado para gerar umLongStream aplicando a funçãolength em cada elemento - após o que podemossume obter um resultado final.

5. Com Apache Commons IO

A seguir - vamos ver como obter o tamanho da pasta usandoApache Commons IO. No exemplo a seguir - simplesmente usamosFileUtils.sizeOfDirectory() para obter o tamanho da pasta:

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

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

    assertEquals(expectedSize, size);
}

Observe que esse método utilitário de ponto a ponto implementa uma solução Java 6 simples sob o capô.

Além disso, observe que a biblioteca também fornece um métodoFileUtils.sizeOfDirectoryAsBigInteger() que lida melhor com diretórios restritos de segurança.

6. Com goiaba

Agora - vamos ver como calcular o tamanho de uma pasta usandoGuava. No exemplo a seguir - usamosFiles.fileTreeTraverser() para percorrer todos os arquivos na pasta e somar seus tamanhos:

@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. Tamanho legível por humanos

Finalmente - vamos ver como obter uma representação mais legível do usuário do tamanho da pasta - não apenas um tamanho em bytes:

@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);
}

Nota: UsamosDecimalFormat(“,#0,#”) para arredondar o resultado em uma casa decimal.

8. Notas

Aqui estão algumas notas sobre o cálculo do tamanho da pasta:

  • TantoFiles.walk()eFiles.walkFileTree() lançarão uma SecurityException se o gerenciador de segurança negar acesso ao arquivo inicial.

  • O loop infinito pode ocorrer se a pasta contiver links simbólicos.

9. Conclusão

Neste tutorial rápido, ilustramos exemplos do uso de diferentes versões deJava,Apache Commons IOeGuava para calcular o tamanho de um diretório no sistema de arquivos.

A implementação desses exemplos pode ser encontrada emthe GitHub project - este é um projeto baseado em Maven, portanto, deve ser fácil de importar e executar como está.