Ottieni dimensioni della cartella o del file

Come posso recuperare la dimensione della cartella o del file in Java?

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

Ciò restituisce la lunghezza del file in byte o 0 se il file non esiste. Non esiste un modo integrato per ottenere la dimensione di una cartella, dovrai percorrere l’albero delle directory in modo ricorsivo (usando il metodo listFiles() di un object file che rappresenta una directory) e accumulare la dimensione della directory per te:

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

ATTENZIONE : questo metodo non è sufficientemente robusto per l’uso di produzione. directory.listFiles() può restituire null e causare una NullPointerException . Inoltre, non considera i collegamenti simbolici e probabilmente ha altre modalità di errore. Usa questo metodo .

Hai bisogno di FileUtils#sizeOfDirectory(File) da commons-io .

Si noti che è necessario verificare manualmente se il file è una directory poiché il metodo genera un’eccezione se viene passata una non directory.

AVVERTENZA : questo metodo (come commons-io 2.4) ha un bug e può lanciare IllegalArgumentException se la directory viene modificata contemporaneamente.

Usando java-7 nio api, il calcolo della dimensione della cartella può essere fatto molto più velocemente.

Ecco un esempio pronto per l’esecuzione che è robusto e non genererà un’eccezione. Registrerà le directory che non può entrare o ha avuto problemi di attraversamento. I collegamenti simbolici vengono ignorati e la modifica simultanea della directory non causerà più problemi del necessario.

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

In Java 8:

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

Sarebbe più carino usare Files::size nel passo della mappa ma lancia un’eccezione controllata.

AGGIORNARE:
Dovresti anche essere consapevole che questo può generare un’eccezione se alcuni file / cartelle non sono accessibili. Vedi questa domanda e un’altra soluzione usando Guava .

File.length() ( Javadoc ).

Nota che questo non funziona per le directory, o non è garantito che funzioni.

Per una directory, cosa vuoi? Se è la dimensione totale di tutti i file sottostanti, puoi camminare in modo ricorsivo ai bambini usando File.list() e File.isDirectory() e sumre le loro dimensioni.

L’object File ha un metodo di length :

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

Ecco il modo migliore per ottenere una dimensione generale del file (funziona per directory e non directory):

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

Modifica: si noti che questa operazione probabilmente richiederà molto tempo. Non eseguirlo sul thread dell’interfaccia utente.

Inoltre, qui (tratto da https://stackoverflow.com/a/5599842/1696171 ) è un buon modo per ottenere una stringa leggibile dall’utente dalla lunga restituita:

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

Per Java 8 questo è un modo giusto per farlo:

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

È importante filtrare tutte le directory , poiché non è garantito che il metodo di lunghezza sia 0 per le directory.

Almeno questo codice fornisce le stesse informazioni sulle dimensioni come fa Windows Explorer.

Se si desidera utilizzare l’API NIO Java 8 , il seguente programma stamperà la dimensione, in byte, della directory in cui si trova.

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

Il metodo calculateSize è universale per gli oggetti Path , quindi funziona anche per i file. Nota che se un file o una directory sono inaccessibili, in questo caso la dimensione restituita dell’object percorso sarà 0 .

  • Funziona per Android e Java
  • Funziona sia per cartelle che per file
  • Controlla ovunque il puntatore nullo dove necessario
  • Ignora collegamenti simbolici o scorciatoie
  • Produzione pronta!

Codice sorgente:

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

Dopo molte ricerche e ricerche sulle diverse soluzioni proposte qui su StackOverflow. Alla fine ho deciso di scrivere la mia soluzione. Il mio scopo è avere un meccanismo di non lancio perché non voglio andare in crash se l’API non è in grado di recuperare la dimensione della cartella. Questo metodo non è adatto per uno scenario multithread.

Prima di tutto voglio controllare le directory valide mentre attraversi la struttura del file system.

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

Secondo, non voglio che la mia chiamata ricorsiva entri nei collegamenti simbolici (softlink) e includa la dimensione nell’aggregato totale.

 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 la mia implementazione basata sulla ricorsione per recuperare la dimensione della directory specificata. Si noti il ​​controllo nullo per dir.listFiles (). Secondo javadoc esiste la possibilità che questo metodo possa restituire null.

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

Qualche crema sulla torta, l’API per ottenere la dimensione della lista File (potrebbe essere tutti i file e la cartella sotto root).

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

in linux se vuoi ordinare le directory allora du -hs * | ordina -h