Java–ディレクトリサイズ
1. 概要
このチュートリアルでは、Java 6、7、新しいJava 8、およびGuavaとApache Common IOを使用して、Java内のフォルダーのサイズを取得する方法を学習します。
最後に、ディレクトリサイズの人間が読める形式の表現も取得します。
2. Javaを使用
フォルダのサイズを計算する簡単な例から始めましょう–その内容の合計を使用して:
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. Java7を使用
次へ– Java7を使用してフォルダーサイズを取得する方法を見てみましょう。 次の例では、 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. Java8を使用
それでは、 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()は、各要素にlength関数を適用してLongStreamを生成するために使用されます。その後、sumと最終結果を取得します。
5. ApacheCommonsIOを使用
次へ– Apache CommonsIOを使用してフォルダーサイズを取得する方法を見てみましょう。 次の例では、 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);
}
これは、ポイントユーティリティメソッドが内部で単純なJava6ソリューションを実装していることに注意してください。
また、ライブラリには、セキュリティが制限されたディレクトリをより適切に処理する 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、#”)を使用して、結果を小数点以下1桁に丸めました。
8. ノート
フォルダサイズの計算に関する注意事項は次のとおりです。
- Files.walk()と Files.walkFileTree()はどちらも、セキュリティマネージャーが開始ファイルへのアクセスを拒否した場合にSecurityExceptionをスローします。
- フォルダにシンボリックリンクが含まれている場合、無限ループが発生する可能性があります。
9. 結論
このクイックチュートリアルでは、さまざまな Java バージョン、 Apache CommonsIOおよびGuavaを使用して、ファイルシステム内のディレクトリのサイズを計算する例を示しました。
これらの例の実装は、 GitHubプロジェクトにあります。これはMavenベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。