После долгих исследований и изучения различных решений, предлагаемых здесь, в StackOverflow. Я наконец решил написать свое собственное решение. Моя цель состоит в том, чтобы иметь механизм безбрасывания, потому что я не хочу аварийно завершать работу, если API не может получить размер папки. Этот метод не подходит для многопоточного сценария.
Прежде всего, я хочу проверить правильность каталогов при обходе дерева файловой системы.
private static boolean isValidDir(File dir){
if (dir != null && dir.exists() && dir.isDirectory()){
return true;
}else{
return false;
}
}
Во-вторых, я не хочу, чтобы мой рекурсивный вызов входил в символические ссылки (программные ссылки) и включал размер в общую совокупность.
public static boolean isSymlink(File file) throws IOException {
File canon;
if (file.getParent() == null) {
canon = file;
} else {
canon = new File(file.getParentFile().getCanonicalFile(),
file.getName());
}
return !canon.getCanonicalFile().equals(canon.getAbsoluteFile());
}
Наконец, моя рекурсивная реализация для извлечения размера указанного каталога. Обратите внимание на нулевую проверку для dir.listFiles (). Согласно javadoc, существует вероятность того, что этот метод может вернуть ноль.
public static long getDirSize(File dir){
if (!isValidDir(dir))
return 0L;
File[] files = dir.listFiles();
//Guard for null pointer exception on files
if (files == null){
return 0L;
}else{
long size = 0L;
for(File file : files){
if (file.isFile()){
size += file.length();
}else{
try{
if (!isSymlink(file)) size += getDirSize(file);
}catch (IOException ioe){
//digest exception
}
}
}
return size;
}
}
Немного крема на торте, API для получения размера списка файлов (может быть все файлы и папки в корневом каталоге).
public static long getDirSize(List<File> files){
long size = 0L;
for(File file : files){
if (file.isDirectory()){
size += getDirSize(file);
} else {
size += file.length();
}
}
return size;
}