Obtener el tamaño de la carpeta o archivo

¿Cómo puedo recuperar el tamaño de la carpeta o archivo en Java?

java.io.File file = new java.io.File("myfile.txt"); file.length(); 

Esto devuelve la longitud del archivo en bytes o 0 si el archivo no existe. No hay una forma integrada de obtener el tamaño de una carpeta, tendrá que recorrer el árbol de directorios recursivamente (usando el método listFiles() de un objeto de archivo que representa un directorio) y acumular el tamaño del directorio por su cuenta:

 public static long folderSize(File directory) { long length = 0; for (File file : directory.listFiles()) { if (file.isFile()) length += file.length(); else length += folderSize(file); } return length; } 

ADVERTENCIA : este método no es lo suficientemente robusto para el uso de producción. directory.listFiles() puede devolver null y causar una NullPointerException . Además, no tiene en cuenta los enlaces simbólicos y posiblemente tenga otros modos de falla. Usa este método

Necesita FileUtils#sizeOfDirectory(File) de commons-io .

Tenga en cuenta que deberá verificar manualmente si el archivo es un directorio, ya que el método arroja una excepción si se le pasa un elemento que no sea de directorio.

ADVERTENCIA : Este método (a partir de commons-io 2.4) tiene un error y puede arrojar IllegalArgumentException si el directorio se modifica simultáneamente.

Usando java-7 nio api, calcular el tamaño de la carpeta se puede hacer mucho más rápido.

Aquí hay un ejemplo listo para ejecutar que es robusto y no generará una excepción. Registrará directorios que no puede ingresar o que tuvo problemas para atravesar. Los enlaces simbólicos se ignoran, y la modificación simultánea del directorio no causará más problemas de los necesarios.

 /** * Attempts to calculate the size of a file or directory. * * 

* Since the operation is non-atomic, the returned value may be inaccurate. * However, this method is quick and does its best. */ public static long size(Path path) { final AtomicLong size = new AtomicLong(0); try { Files.walkFileTree(path, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { size.addAndGet(attrs.size()); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) { System.out.println("skipped: " + file + " (" + exc + ")"); // Skip folders that can't be traversed return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) { if (exc != null) System.out.println("had trouble traversing: " + dir + " (" + exc + ")"); // Ignore errors traversing a folder return FileVisitResult.CONTINUE; } }); } catch (IOException e) { throw new AssertionError("walkFileTree will not throw IOException if the FileVisitor does not"); } return size.get(); }

 public static long getFolderSize(File dir) { long size = 0; for (File file : dir.listFiles()) { if (file.isFile()) { System.out.println(file.getName() + " " + file.length()); size += file.length(); } else size += getFolderSize(file); } return size; } 

En Java 8:

 long size = Files.walk(path).mapToLong( p -> p.toFile().length() ).sum(); 

Sería más agradable usar Files::size en el paso del mapa pero arroja una excepción marcada.

ACTUALIZAR:
También debe tener en cuenta que esto puede arrojar una excepción si algunos de los archivos / carpetas no son accesibles. Vea esta pregunta y otra solución usando Guava .

File.length() ( Javadoc ).

Tenga en cuenta que esto no funciona para directorios, o no se garantiza que funcione.

Para un directorio, ¿qué quieres? Si se trata del tamaño total de todos los archivos que se encuentran debajo, puede caminar a los niños de manera recursiva usando File.list() y File.isDirectory() y sumr sus tamaños.

El objeto File tiene un método de length :

 f = new File("your/file/name"); f.length(); 

Esta es la mejor forma de obtener el tamaño general de un archivo (funciona para el directorio y sin el directorio):

 public static long getSize(File file) { long size; if (file.isDirectory()) { size = 0; for (File child : file.listFiles()) { size += getSize(child); } } else { size = file.length(); } return size; } 

Editar: Tenga en cuenta que esta va a ser una operación lenta. No lo ejecute en el hilo de UI.

Además, aquí (tomado de https://stackoverflow.com/a/5599842/1696171 ) es una buena forma de obtener una cadena legible por el usuario desde la devolución larga:

 public static String getReadableSize(long size) { if(size < = 0) return "0"; final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" }; int digitGroups = (int) (Math.log10(size)/Math.log10(1024)); return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups)) + " " + units[digitGroups]; } 

Para Java 8 esta es una forma correcta de hacerlo:

 Files.walk(new File("D:/temp").toPath()) .map(f -> f.toFile()) .filter(f -> f.isFile()) .mapToLong(f -> f.length()).sum() 

Es importante filtrar todos los directorios , porque no se garantiza que el método de longitud sea 0 para los directorios.

Al menos este código ofrece la misma información de tamaño que el Explorador de Windows.

Si desea utilizar Java 8 NIO API, el siguiente progtwig imprimirá el tamaño, en bytes, del directorio en el que se encuentra.

 import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class PathSize { public static void main(String[] args) { Path path = Paths.get("."); long size = calculateSize(path); System.out.println(size); } /** * Returns the size, in bytes, of the specified path. If the given * path is a regular file, trivially its size is returned. Else the path is * a directory and its contents are recursively explored, returning the * total sum of all files within the directory. * 

* If an I/O exception occurs, it is suppressed within this method and * 0 is returned as the size of the specified path. * * @param path path whose size is to be returned * @return size of the specified path */ public static long calculateSize(Path path) { try { if (Files.isRegularFile(path)) { return Files.size(path); } return Files.list(path).mapToLong(PathSize::calculateSize).sum(); } catch (IOException e) { return 0L; } } }

El método calculateSize es universal para objetos Path , por lo que también funciona para archivos. Tenga en cuenta que si un archivo o directorio es inaccesible, en este caso el tamaño devuelto del objeto de ruta será 0 .

  • Funciona para Android y Java
  • Funciona para carpetas y archivos
  • Comprueba el puntero nulo en todas partes donde sea necesario
  • Ignora accesos simbólicos, también conocidos como accesos directos
  • ¡Producción lista!

Código fuente:

  public long fileSize(File root) { if(root == null){ return 0; } if(root.isFile()){ return root.length(); } try { if(isSymlink(root)){ return 0; } } catch (IOException e) { e.printStackTrace(); return 0; } long length = 0; File[] files = root.listFiles(); if(files == null){ return 0; } for (File file : files) { length += fileSize(file); } return length; } private static boolean isSymlink(File file) throws IOException { File canon; if (file.getParent() == null) { canon = file; } else { File canonDir = file.getParentFile().getCanonicalFile(); canon = new File(canonDir, file.getName()); } return !canon.getCanonicalFile().equals(canon.getAbsoluteFile()); } 
 public long folderSize (String directory) { File curDir = new File(directory); long length = 0; for(File f : curDir.listFiles()) { if(f.isDirectory()) { for ( File child : f.listFiles()) { length = length + child.length(); } System.out.println("Directory: " + f.getName() + " " + length + "kb"); } else { length = f.length(); System.out.println("File: " + f.getName() + " " + length + "kb"); } length = 0; } return length; } 

Después de investigar mucho y buscar diferentes soluciones propuestas aquí en StackOverflow. Finalmente decidí escribir mi propia solución. Mi propósito es tener un mecanismo de no lanzamiento porque no quiero colapsar si la API no puede recuperar el tamaño de la carpeta. Este método no es adecuado para escenarios de subprocesos múltiples.

Antes que nada quiero verificar si hay directorios válidos mientras recorro el árbol del sistema de archivos.

 private static boolean isValidDir(File dir){ if (dir != null && dir.exists() && dir.isDirectory()){ return true; }else{ return false; } } 

En segundo lugar, no quiero que mi llamada recursiva vaya a enlaces simbólicos (softlinks) e incluir el tamaño en total agregado.

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

Finalmente, mi implementación basada en la recursividad para obtener el tamaño del directorio especificado. Observe la comprobación nula de dir.listFiles (). Según javadoc, existe la posibilidad de que este método pueda devolver nulo.

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

Un poco de crema en la torta, la API para obtener el tamaño de la lista de archivos (podría ser todos los archivos y carpetas en la raíz).

 public static long getDirSize(List files){ long size = 0L; for(File file : files){ if (file.isDirectory()){ size += getDirSize(file); } else { size += file.length(); } } return size; } 

en Linux si quieres ordenar directorios, entonces du -hs * | ordenar -h