2011-08-31 17 views
32

¿Cómo puedo obtener el tamaño de un archivo o directorio utilizando el nuevo NIO en java 7?Obtener tamaño de archivo/directorio con Java 7 nuevo IO

+0

¿Qué pasa con la forma antigua? A menos que haya compatibilidad para el tamaño de directorio recursivo ahora. ¿Esta ahí? – Thilo

+0

he oído que es mucho más rápido. y quiero probar eso. – clamp

+0

Tengo que preguntarme cómo puede ser más rápido ... – Thilo

Respuesta

40

Usa Files.size(Path) para obtener el tamaño de un archivo.

Para el tamaño de un directorio (es decir, el tamaño de todos los archivos que contiene), aún necesita volver a generar manualmente, hasta donde yo sé.

+0

Creo que el método anterior no está presente en Java7 I/O. Compruebe una vez – developer

+1

@Damodar: mi respuesta contiene un enlace a JavaDoc. ¿Por qué crees que no está presente? –

+1

Se vinculó a los documentos API oficiales de Oracle. El método está ahí. – Thilo

5
MutableLong size = new MutableLong(); 
Files.walkFileTree(directoryPath, new SimpleFileVisitor<Path>() { 
      @Override 
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 
       size.add(attrs.size()); 
      } 
} 

Esto calcularía el tamaño de todos los archivos en un directorio. Sin embargo, tenga en cuenta que todos los archivos en el directorio deben ser archivos regulares, ya que API especifica el método de tamaño de BasicFileAttributes:

"El tamaño de los archivos que no son archivos regulares es específico de la implementación y por lo tanto no especificado."

Si se topa con un archivo no regulado, tendrá que no incluirlo en tamaño o devolver un tamaño desconocido. Puede verificar si el archivo es regular con

BasicFileAttributes.isRegularFile() 
+0

Buena respuesta, y para cualquiera que se pregunte si las clases Mutable * para primitivos son parte de apache.commons.lang – Nicholi

6

Aquí hay un ejemplo listo para ejecutar que también omitirá los directorios que no puede ingresar. Utiliza java.util.concurrent.atomic.AtomicLong para acumular estado.

public static void main(String[] args) throws IOException { 
    Path path = Paths.get("c:/"); 
    long size = getSize(path); 
    System.out.println("size=" + size); 
} 

static long getSize(Path startPath) throws IOException { 
    final AtomicLong size = new AtomicLong(0); 

    Files.walkFileTree(startPath, new SimpleFileVisitor<Path>() { 
     @Override 
     public FileVisitResult visitFile(Path file, 
       BasicFileAttributes attrs) throws IOException { 
      size.addAndGet(attrs.size()); 
      return FileVisitResult.CONTINUE; 
     } 

     @Override 
     public FileVisitResult visitFileFailed(Path file, IOException exc) 
       throws IOException { 
      // Skip folders that can't be traversed 
      System.out.println("skipped: " + file + "e=" + exc); 
      return FileVisitResult.CONTINUE; 
     } 
    }); 

    return size.get(); 
} 
+0

¿Se pregunta por qué es necesario 'AtomicLong'? ¿Por qué no solo un "largo"? ¿Hay algo en paralelo sobre [walkFileTree] (http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#walkFileTree%28java.nio.file.Path,%20java. util.Set,% 20int,% 20java.nio.file.FileVisitor% 29)? – peterh

+0

tbh, simplemente reescribí la otra respuesta sin usar 3pp (MutableLong). Pero creo que la variable tiene que ser "definitiva" para acceder desde la clase anónima interna. Que AtomicLong permite. –

+0

El método 'postVisitDirectory' también puede ser anulado. No es necesario marcar la referencia 'size' como final aquí porque no se cambia en la clase anónima interna. Solo se cambia su contenido (valor). Se puede usar una matriz larga (con un solo elemento) en lugar de AtomicLong. – Stephan