Comment puis-je récupérer la taille d'un dossier ou d'un fichier en Java?
Java.io.File file = new Java.io.File("myfile.txt");
file.length();
Cela renvoie la longueur du fichier en octets ou 0
si le fichier n'existe pas. Il n'y a pas de moyen intégré pour obtenir la taille d'un dossier, vous devrez parcourir l'arborescence de répertoires de manière récursive (à l'aide de la méthode listFiles()
d'un objet fichier représentant un répertoire) et accumuler la taille de répertoire pour vous-même:
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;
}
WARNING: cette méthode n'est pas suffisamment robuste pour une utilisation en production. directory.listFiles()
peut renvoyer null
et provoquer une NullPointerException
. En outre, il ne prend pas en compte les liens symboliques et peut avoir d’autres modes de défaillance. Utilisez cette méthode .
Vous avez besoin de FileUtils#sizeOfDirectory(File)
from commons-io .
Notez que vous devrez vérifier manuellement si le fichier est un répertoire car la méthode lève une exception si un non-répertoire lui est transmis.
WARNING: Cette méthode (à compter de commons-io 2.4) a un bogue et peut lancer IllegalArgumentException
si le répertoire est modifié simultanément.
Avec Java-7 nio api, le calcul de la taille du dossier est beaucoup plus rapide.
Voici un exemple prêt à l'emploi qui est robuste et ne lève pas d'exception. Il enregistrera les répertoires qu'il ne peut pas entrer ou qu'il a eu du mal à parcourir. Les liens symboliques sont ignorés et une modification simultanée du répertoire ne causera pas plus de problèmes que nécessaire.
/**
* Attempts to calculate the size of a file or directory.
*
* <p>
* 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<Path>() {
@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();
}
En Java 8:
long size = Files.walk(path).mapToLong( p -> p.toFile().length() ).sum();
Il serait préférable d'utiliser Files::size
dans l'étape de mappage, mais une exception vérifiée est émise.
METTRE À JOUR:
Vous devez également savoir que cela peut générer une exception si certains fichiers/dossiers ne sont pas accessibles. Voir cette question et une autre solution utilisant Guava .
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;
}
Voici le meilleur moyen d'obtenir la taille d'un fichier général (fonctionne pour les répertoires et les non répertoires):
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;
}
Edit: Notez que cette opération prendra probablement beaucoup de temps. Ne l'exécutez pas sur le fil de l'interface utilisateur.
De plus, voici (extrait de https://stackoverflow.com/a/5599842/1696171 ) un moyen pratique d'obtenir une chaîne lisible par l'utilisateur à partir du long retour:
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];
}
File.length()
( Javadoc ).
Notez que cela ne fonctionne pas pour les répertoires ou que son fonctionnement n’est pas garanti.
Que voulez-vous d'un répertoire? S'il s'agit de la taille totale de tous les fichiers situés en dessous, vous pouvez promener récursivement les enfants en utilisant File.list()
et File.isDirectory()
et en faire la somme.
L'objet File
a une méthode length
:
f = new File("your/file/name");
f.length();
Pour Java 8 c’est une bonne façon de le faire:
Files.walk(new File("D:/temp").toPath())
.map(f -> f.toFile())
.filter(f -> f.isFile())
.mapToLong(f -> f.length()).sum()
Il est important de filtrer tous les répertoires , car la méthode de longueur n'est pas garantie à 0 pour les répertoires.
Au moins ce code fournit les mêmes informations de taille que l'explorateur Windows lui-même.
Code source:
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());
}
sous linux si vous voulez trier les répertoires puis du -hs * | trier -h
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;
}
pour les fenêtres, en utilisant Java.io, cette fonction récurrente est utile.
public static long folderSize(File directory) {
long length = 0;
if (directory.isFile())
length += directory.length();
else{
for (File file : directory.listFiles()) {
if (file.isFile())
length += file.length();
else
length += folderSize(file);
}
}
return length;
}
Ceci est testé et fonctionne correctement de mon côté.
Après de nombreuses recherches et recherches sur les différentes solutions proposées ici chez StackOverflow. J'ai finalement décidé d'écrire ma propre solution. Mon but est d’avoir un mécanisme de non-projection car je ne veux pas planter si l’API ne parvient pas à récupérer la taille du dossier. Cette méthode ne convient pas au scénario multithread.
Tout d'abord, je veux vérifier les répertoires valides tout en parcourant l'arborescence du système de fichiers.
private static boolean isValidDir(File dir){
if (dir != null && dir.exists() && dir.isDirectory()){
return true;
}else{
return false;
}
}
Deuxièmement, je ne veux pas que mon appel récursif entre dans des liens symboliques (liens souples) et inclue la taille dans l’agrégat total.
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());
}
Enfin, mon implémentation basée sur la récursivité pour extraire la taille du répertoire spécifié. Notez la vérification null pour dir.listFiles (). Selon javadoc, cette méthode peut renvoyer 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;
}
}
Un peu de crème sur le gâteau, l'API pour obtenir la taille de la liste des fichiers (peut-être tous les fichiers et le dossier sous la racine).
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;
}