Java - ディレクトリサイズ

Java –ディレクトリサイズ

1. 概要

このチュートリアルでは、Java 6、7、新しいJava 8、GuavaおよびApache Common IOを使用してsize of a folder in Javaを取得する方法を学習します。

最後に、人間が読めるディレクトリサイズの表現も取得します。

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()は、各要素にlength関数を適用してLongStreamを生成するために使用されます。その後、sumを実行して最終結果を取得できます。

5. Apache CommonsIOを使用

次へ–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,#”)を使用して、結果を小数点以下1桁に丸めました。

8. ノート

フォルダーサイズの計算に関する注意事項を次に示します。

  • セキュリティマネージャが開始ファイルへのアクセスを拒否した場合、Files.walk()Files.walkFileTree()の両方がSecurityExceptionをスローします。

  • フォルダにシンボリックリンクが含まれている場合、無限ループが発生することがあります。

9. 結論

このクイックチュートリアルでは、さまざまなJavaバージョン、Apache Commons IO、およびGuavaを使用して、ファイルシステム内のディレクトリのサイズを計算する例を示しました。

これらの例の実装はthe GitHub projectにあります。これはMavenベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。