Skip to content

Instantly share code, notes, and snippets.

@svdamani
Last active August 29, 2015 14:23
Show Gist options
  • Save svdamani/4e0839f380f76f904621 to your computer and use it in GitHub Desktop.
Save svdamani/4e0839f380f76f904621 to your computer and use it in GitHub Desktop.
Calculate size of file system sub tree in Java (java.nio.files.*)
/**
* File : FileSize.java
* Purpose : Concurrently process a filesystem sub-tree and calculate it's size
* Author : Shreevardhan
* Compilation : `javac FileSize.java`
* Execution : `java FileSize <path> <threads>`
*/
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicLong;
public class FileSize {
public static void main(String[] args) throws IOException {
Path path = Paths.get(System.getProperty("user.home"));
int threads = Runtime.getRuntime().availableProcessors();
if (args.length >= 1)
path = Paths.get(args[0]);
if (args.length == 2)
threads = Integer.parseInt(args[1]);
long result = new FileSize().get(path, threads);
System.out.println(prettify(result) + "\t" + path);
}
static String prettify(Long size) {
if (size <= 0) return "0";
int digits = (int) (Math.log10(size) / Math.log10(1024));
String[] units = new String[] { "B", "KB", "MB", "GB" };
return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digits)) + units[digits];
}
private Long get(Path path, int threads) {
ForkJoinPool pool = new ForkJoinPool(threads);
try {
return pool.invoke(new FileSizeTask(path));
} finally {
pool.shutdown();
}
}
}
class FileSizeTask extends RecursiveTask<Long> {
private Path path;
public FileSizeTask(Path path) {
this.path = path;
}
@Override
protected Long compute() {
List<FileSizeTask> tasks = new ArrayList<>();
AtomicLong size = new AtomicLong();
try {
Files.walkFileTree(path, EnumSet.of(FileVisitOption.FOLLOW_LINKS),
Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if (dir.equals(FileSizeTask.this.path)) {
size.addAndGet(attrs.size());
return FileVisitResult.CONTINUE;
}
FileSizeTask task = new FileSizeTask(dir);
task.fork();
tasks.add(task);
return FileVisitResult.SKIP_SUBTREE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
size.addAndGet(attrs.size());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path p, IOException e) {
System.err.println("Error: Cannot read " + p);
return FileVisitResult.CONTINUE;
}
});
}
catch (IOException e) {
e.printStackTrace();
}
for (FileSizeTask task : tasks)
size.addAndGet(task.join());
return size.get();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment