Klasör veya dosya boyutunu alın


105

Java'da klasör veya dosya boyutunu nasıl alabilirim?



Üzerinde olmak olur Android'in ardından bakabilirsiniz StatFs. Dosya sistemi istatistiklerini kullanır ve ihtiyaçlarımız için kullanılamayan yinelemeli yöntemlerden yaklaşık 1000 kat daha hızlıdır. Uygulamamıza buradan ulaşabilirsiniz: stackoverflow.com/a/58418639/293280
Joshua Pinter

Yanıtlar:


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

Bu, dosyanın uzunluğunu bayt olarak veya 0dosya yoksa döndürür . Bir klasörün boyutunu almanın yerleşik bir yolu yoktur, dizin ağacını yinelemeli olarak yürümeniz ( listFiles()bir dizini temsil eden bir dosya nesnesi yöntemini kullanarak ) ve dizin boyutunu kendiniz için toplamanız gerekir:

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

UYARI : Bu yöntem, üretim kullanımı için yeterince sağlam değildir. directory.listFiles()geri dönebilir nullve a neden olabilir NullPointerException. Ayrıca, sembolik bağları dikkate almaz ve muhtemelen başka hata modlarına sahiptir. Bu yöntemi kullanın .


11
Bunu bir Windows makinesinde C: kök dizininde çalıştırırsanız dikkatli olun; orada (java.io.File'a göre) ne dosya ne de dizin olmayan bir sistem dosyası var. Dosyanın aslında bir dizin olup olmadığını kontrol etmek için else-cümlesini değiştirmek isteyebilirsiniz.
Paul Clapham

2
Yöntemin başlangıcında bir dizin olup olmadığını görmek için parametreyi kontrol etmek için basit bir değişiklik ve uzunluğu döndür, sonra özyineleme daha basittir - sadece aynı yönteme self çağrısını ekleyin ve ardından bu, bunun yerine bir dosya referansının iletilmesini destekler bir dizinin de.
Kevin Brock

3
Java 7 veya üstünü kullanıyorsanız, stackoverflow.com/a/19877372/40064 yanıtını kullanın, çok daha hızlıdır.
Wim Deblauwe

1
Bu sembolik bağlarla karıştırılacaktır. Ayrıca, NullPointerExceptiondizin eşzamanlı olarak değiştirilirse bir atabilir .
Aleksandr Dubinsky

43

Java-7 nio api kullanarak, klasör boyutunun hesaplanması çok daha hızlı yapılabilir.

İşte sağlam ve bir istisna oluşturmayan çalıştırmaya hazır bir örnek. Giremediği veya geçerken sorun yaşadığı dizinleri günlüğe kaydeder. Sembolik bağlantılar göz ardı edilir ve dizinin aynı anda değiştirilmesi gerekenden daha fazla soruna neden olmaz.

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

Android geliştirmede bunun bir eşdeğeri var mı?
android geliştiricisi

AtomicLongSadece kullanmak yerine kullanmanın bir nedeni var mı long?
Lukas Schmelzeisen

Anonim sınıftan erişildiğinde değişkenin nihai olması gerekir
Aksel Willgert

1
JMH kullanarak bir kıyaslama yaptım ve bu NIO api yöntemi, ortak kod ile karşılaştırıldığında yaklaşık 4 ila 5 kat daha hızlıdır (toplam 180229 dosya için birçok alt klasörün bulunduğu bir klasörde test edilmiştir). Commons IO 15 saniye, NIO 5 saniye sürdü.
Wim Deblauwe

3
Bu yaklaşım en sağlam olanıdır. Sembolik bağlar, eşzamanlı değişiklik, güvenlik istisnaları ile ilgilenir, hem dosyalar hem de dizinlerle çalışır, vb. Çok kötü Files, doğrudan desteklemiyor!
Aleksandr Dubinsky

38

İhtiyacınız FileUtils#sizeOfDirectory(File)gelen commons-io .

Yöntem, dizin olmayan bir dosyaya aktarılırsa bir istisna attığından, dosyanın bir dizin olup olmadığını manuel olarak kontrol etmeniz gerekeceğini unutmayın.

UYARI : Bu yöntemde (commons-io 2.4 itibariyle) bir hata vardır ve IllegalArgumentExceptiondizin eşzamanlı olarak değiştirilirse hata verebilir .


Peki dosya bir dizin değilse ne olur? yokken? vb - ne kadar berbat dokümanlar
Mr_and_Mrs_D

@Mr_and_Mrs_D - checkDirectory(directory);Kontrolün ardından satırları kopyalayıp yapıştırmanız yeterlidir . Sadece File.listFilesçocuğu olduğundan emin ol . Refs: FileUtils.sizeOfDirectory () , File.listFiles ()
Sayın Polywhirl

3
Hata IO-449'a bakın . Bu yöntem IllegalArgumentException, dizin yinelenirken değiştirilirse bir atar .
Aleksandr Dubinsky

ah !!! Bu berbat ... evet, dosyaları listeler ve sonra kod çalışırken biri silinirse atar.
Dean Hiller

19

Java 8'de:

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

Files::sizeHarita adımında kullanmak daha güzel olurdu , ancak kontrol edilen bir istisna atıyor.

GÜNCELLEME:
Bazı dosyalara / klasörlere erişilemiyorsa bunun bir istisna oluşturabileceğini de bilmelisiniz. Guava kullanarak bu soruyu ve başka bir çözümü görün .


1
Benzer bir şeye bakıyordum ve söz konusu kodla son buldum: stackoverflow.com/questions/22867286/… , gördüğünüz gibi, hata işlemenin başka bir yönü de sorunlara neden oluyor.
Aksel Willgert

@AkselWillgert Teşekkürler, bu talihsiz bir durum ve cevabı güncelledim. Şimdi Guava stackoverflow.com/a/24757556/1180621'e
geçiliyor

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

1
@Vishal kodunuzun basit bir düzeltmeye sahip olması gerekir, özyinelemeli çağrıda boyutu yalnızca ona atamakla kalmayıp, mevcut boyuta eklemelisiniz. size += getFolderSize(file);
Teja Kantamneni

@Teja: İşaret ettiğiniz için teşekkürler, ancak değişiklikler if ifadesinde de olacak
Vishal

Bazen büyüyen bir klasörde (başka bir iş parçacığı dosya ve klasörleri indiriyor ve aynı zamanda ilerledikçe klasör boyutunu yazdırıyorum) "for (File file: dir.listFiles ()) {" satırında nullpointerexception veriyor . Bazı dosyalar canlı bir klasörde hızla görünür ve kaybolur. Bu yüzden for döngüsünden önce dir.listFiles () dönüş değeri için boş bir kontrol ekledim .
csonuryilmaz

Javadoc) (File.listFiles Gönderen: "dizini boş ise dizi boş olacaktır döner. Boş bir I / O hatası oluşursa bu soyut yol adı bir dizin belirtmek etmezse veya." Bu nedenle, dinamik olarak değişen klasörlerde klasör boyutunu alırken yukarıdaki açıklama yararlıdır.
csonuryilmaz

7

İçin Java 8 bunu yapmak için tek bir doğru yolu şudur:

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

Tüm dizinleri filtrelemek önemlidir , çünkü uzunluk yönteminin dizinler için 0 olması garanti edilmez.

En azından bu kod, Windows Gezgini'nin yaptığı gibi aynı boyutta bilgi sağlar.


4

Genel bir Dosya boyutunu almanın en iyi yolu (dizin ve dizin dışı için geçerlidir):

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

Düzenleme: Bunun muhtemelen zaman alıcı bir işlem olacağını unutmayın. UI iş parçacığında çalıştırmayın.

Ayrıca, burada ( https://stackoverflow.com/a/5599842/1696171 adresinden alınmıştır ), uzun süre döndürülen dosyadan kullanıcı tarafından okunabilir bir String elde etmenin güzel bir yoludur:

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

4

Java 8 NIO API kullanmak istiyorsanız , aşağıdaki program bulunduğu dizinin boyutunu bayt olarak yazdıracaktır.

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 <tt>path</tt>. 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.
     * <p>
     * If an I/O exception occurs, it is suppressed within this method and
     * <tt>0</tt> is returned as the size of the specified <tt>path</tt>.
     * 
     * @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;
        }
    }

}

calculateSizeYöntem için evrenseldir Pathnesneler, bu nedenle de dosyaları için çalışır. Not Bir dosya veya dizin erişilemez ise, bu durumda döndüğünü boyut yolu nesnenin olacaktır 0.


3

File.length()( Javadoc ).

Bunun dizinler için çalışmadığını veya çalışmasının garanti edilmediğini unutmayın.

Bir dizin için ne istiyorsun? Altındaki tüm dosyaların toplam boyutuysa, çocukları kullanarak File.list()ve File.isDirectory()boyutlarını toplayarak yinelemeli olarak yürüyebilirsiniz .


3

FileNesne bir sahiptir lengthyöntem:

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

3
  • Android ve Java için çalışır
  • Hem klasörler hem de dosyalar için çalışır
  • Gerektiğinde her yerde boş gösterici olup olmadığını denetler
  • Kısayollar gibi sembolik bağlantıyı yok sayar
  • Üretime hazır!

Kaynak kodu:

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

1

Windows için, java.io kullanarak bu yinelemeli işlev yararlıdır.

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

Bu benim tarafımda test edildi ve düzgün çalışıyor.


1

Test ettim du -c <folderpath>ve nio'dan 2 kat daha hızlı. Dosyalar veya özyineleme

private static long getFolderSize(File folder){
  if (folder != null && folder.exists() && folder.canRead()){
    try {
      Process p = new ProcessBuilder("du","-c",folder.getAbsolutePath()).start();
      BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
      String total = "";
      for (String line; null != (line = r.readLine());)
        total = line;
      r.close();
      p.waitFor();
      if (total.length() > 0 && total.endsWith("total"))
        return Long.parseLong(total.split("\\s+")[0]) * 1024;
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
  return -1;
}

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

0

StackOverflow'da burada önerilen farklı çözümleri araştırıp inceledikten sonra. Sonunda kendi çözümümü yazmaya karar verdim. Amacım, atılmayan mekanizmaya sahip olmak çünkü API klasör boyutunu getiremezse çökmek istemiyorum. Bu yöntem, çok iş parçacıklı senaryo için uygun değildir.

Öncelikle, dosya sistemi ağacında dolaşırken geçerli dizinleri kontrol etmek istiyorum.

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

İkincisi, özyinelemeli çağrımın sembolik bağlantılara (yumuşak bağlantılar) gitmesini ve boyutu toplam kümeye dahil etmesini istemiyorum.

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

Son olarak, belirtilen dizinin boyutunu almak için özyineleme tabanlı uygulamam. Dir.listFiles () için boş kontrole dikkat edin. Javadoc'a göre bu yöntemin null döndürme olasılığı vardır.

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

Pasta üzerinde biraz krem ​​\ u200b \ u200b, listedeki dosyaların boyutunu almak için API (kök altındaki tüm dosyalar ve klasörler olabilir).

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

0

linux'ta dizinleri sıralamak istiyorsanız du -hs * | sort -h


0

Kullanabilirsiniz Apache Commons IOKlasör boyutunu kolayca bulmak için .

Eğer maven'deyseniz, lütfen pom.xmldosyanıza aşağıdaki bağımlılığı ekleyin .

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

Maven hayranı değilse, aşağıdaki jar dosyasını indirin ve sınıf yoluna ekleyin.

https://repo1.maven.org/maven2/commons-io/commons-io/2.6/commons-io-2.6.jar

public long getFolderSize() {

    File folder = new File("src/test/resources");
    long size = FileUtils.sizeOfDirectory(folder);

    return size; // in bytes
}

Dosya boyutunu Commons IO üzerinden almak için,

File file = new File("ADD YOUR PATH TO FILE");

long fileSize = FileUtils.sizeOf(file);

System.out.println(fileSize); // bytes

Ayrıca şu yolla da elde edilebilir: Google Guava

Maven için şunları ekleyin:

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>28.1-jre</version>
</dependency>

Maven kullanmıyorsanız, aşağıdakileri sınıf yoluna ekleyin

https://repo1.maven.org/maven2/com/google/guava/guava/28.1-jre/guava-28.1-jre.jar

public long getFolderSizeViaGuava() {
        File folder = new File("src/test/resources");
        Iterable<File> files = Files.fileTreeTraverser()
                .breadthFirstTraversal(folder);
        long size = StreamSupport.stream(files.spliterator(), false)
                .filter(f -> f.isFile())
                .mapToLong(File::length).sum();

        return  size;
    }

Dosya boyutunu almak için,

 File file = new File("PATH TO YOUR FILE");
 long s  = file.length();
 System.out.println(s);

0
private static long getFolderSize(Path folder) {
        try {
            return Files.walk(folder)
                      .filter(p -> p.toFile().isFile())
                      .mapToLong(p -> p.toFile().length())
                      .sum();
        } catch (IOException e) {
            e.printStackTrace();
            return 0L;
        }

Kodunuz iyi görünse de, diğer yanıtlara bir şey kattığından emin değilim. Varsa, açıklamak için lütfen cevabınızı düzenleyin.
Dragonthoughts

Aynı işi daha az kod satırıyla yapmanın güncellenmiş bir sürümüdür.
Jaskaran Singh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.