Dapatkan ukuran folder atau file

105

Bagaimana cara mengambil ukuran folder atau file di Java?

oneat
sumber
Sama tetapi dengan fokus pada efisiensi: stackoverflow.com/questions/116574/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Jika Anda kebetulan menggunakan Android, lihatlah StatFs. Ini menggunakan statistik sistem file dan hampir 1000x lebih cepat daripada metode rekursif, yang tidak dapat digunakan untuk kebutuhan kita. Implementasi kami dapat ditemukan di sini: stackoverflow.com/a/58418639/293280
Joshua Pinter

Jawaban:

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

Ini mengembalikan panjang file dalam byte atau 0jika file tidak ada. Tidak ada cara bawaan untuk mendapatkan ukuran folder, Anda harus berjalan di pohon direktori secara rekursif (menggunakan listFiles()metode objek file yang mewakili direktori) dan mengakumulasi ukuran direktori untuk Anda sendiri:

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

PERINGATAN : Metode ini tidak cukup kuat untuk penggunaan produksi. directory.listFiles()dapat kembali nulldan menyebabkan a NullPointerException. Juga, itu tidak mempertimbangkan symlink dan mungkin memiliki mode kegagalan lain. Gunakan metode ini .

Tendayi Mawushe
sumber
11
Hati-hati jika Anda menjalankan ini di direktori C: root pada mesin Windows; ada file sistem di sana yang (menurut java.io.File) bukan file atau direktori. Anda mungkin ingin mengubah klausa lain untuk memeriksa bahwa File sebenarnya adalah sebuah direktori.
Paul Clapham
2
Perubahan sederhana untuk memeriksa parameter untuk melihat apakah itu bukan direktori di awal metode dan mengembalikan panjangnya maka rekursi lebih sederhana - cukup tambahkan panggilan ke diri sendiri dalam metode yang sama dan kemudian ini mendukung meneruskan referensi file sebagai gantinya dari direktori juga.
Kevin Brock
3
Jika Anda menggunakan Java 7 atau lebih tinggi, gunakan jawaban stackoverflow.com/a/19877372/40064 itu jauh lebih cepat.
Wim Deblauwe
1
Ini akan dibingungkan oleh symlink. Juga, ini mungkin memunculkan NullPointerExceptionjika direktori dimodifikasi secara bersamaan.
Aleksandr Dubinsky
43

Menggunakan java-7 nio api, menghitung ukuran folder bisa dilakukan lebih cepat.

Berikut adalah contoh siap dijalankan yang kuat dan tidak akan mengeluarkan pengecualian. Ini akan mencatat direktori yang tidak dapat dimasuki atau mengalami masalah saat menjelajah. Symlinks diabaikan, dan modifikasi direktori secara bersamaan tidak akan menyebabkan lebih banyak masalah daripada yang diperlukan.

/**
 * 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();
}
Aksel Willgert
sumber
Apakah ada yang setara untuk ini pada pengembangan Android?
Pengembang android
Apakah ada alasan untuk menggunakan, AtomicLongbukan hanya long?
Lukas Schmelzeisen
Variabel harus final ketika diakses dari kelas anonim
Aksel Willgert
1
Saya melakukan benchmark menggunakan JMH dan metode NIO api ini sekitar 4 hingga 5 kali lebih cepat dibandingkan dengan kode commons-io (diuji pada folder dengan banyak subfolder dengan total 180229 file). Commons IO membutuhkan waktu 15 detik, NIO membutuhkan 5 detik.
Wim Deblauwe
3
Pendekatan ini adalah yang paling kuat. Ini berhubungan dengan symlink, modifikasi bersamaan, pengecualian keamanan, bekerja dengan file dan direktori, dll. Sayang Filessekali tidak mendukungnya secara langsung!
Aleksandr Dubinsky
38

Anda membutuhkan FileUtils#sizeOfDirectory(File)dari commons-io .

Perhatikan bahwa Anda perlu memeriksa secara manual apakah file tersebut adalah direktori karena metode ini mengeluarkan pengecualian jika non-direktori diteruskan ke sana.

PERINGATAN : Metode ini (seperti pada commons-io 2.4) memiliki bug dan mungkin muncul IllegalArgumentExceptionjika direktori diubah secara bersamaan.

yegor256
sumber
Jadi apa yang terjadi jika file bukan direktori? ketika tidak ada? dll - betapa buruknya dokumen
Mr_and_Mrs_D
@Mr_and_Mrs_D - Cukup salin dan tempel baris setelah checkDirectory(directory);pemeriksaan. Pastikan saja yang File.listFilesmemiliki anak. Referensi : FileUtils.sizeOfDirectory () , File.listFiles ()
Mr. Polywhirl
3
Lihat bug IO-449 . Metode ini akan menampilkan IllegalArgumentExceptionjika direktori diubah saat iterasi.
Aleksandr Dubinsky
Aduh!!! Itu menyebalkan ... ya, itu mencantumkan file dan kemudian jika ada yang dihapus saat kode sedang berjalan, itu melempar.
Dean Hiller
19

Di Jawa 8:

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

Ini akan lebih baik untuk digunakan Files::sizedalam langkah peta tetapi ini memunculkan pengecualian yang dicentang.

UPDATE:
Anda juga harus menyadari bahwa ini dapat menimbulkan pengecualian jika beberapa file / folder tidak dapat diakses. Lihat pertanyaan ini dan solusi lain menggunakan Jambu Biji .

Andrejs
sumber
1
saya sedang mencari sesuatu yang serupa dan berakhir dengan kode yang dimaksud: stackoverflow.com/questions/22867286/… , seperti yang Anda lihat ada aspek lain dari penanganan kesalahan yang juga menyebabkan masalah.
Aksel Willgert
@AkselWillgert Terima kasih, ini sangat disayangkan dan saya telah memperbarui jawabannya. Sekarang beralih ke Jambu stackoverflow.com/a/24757556/1180621
Andrejs
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;
}
Vishal
sumber
1
@Vishal kode Anda harus memiliki perbaikan sederhana, dalam panggilan rekursif, Anda harus menambahkan ukuran ke ukuran yang ada tidak hanya menetapkannya. size += getFolderSize(file);
Teja Kantamneni
@Teja: Terima kasih telah menunjukkannya, tetapi perubahannya juga akan terjadi pada pernyataan if
Vishal
Kadang-kadang pada folder yang berkembang (utas lain sedang mengunduh file dan folder dan pada saat yang sama saya mencetak ukuran folder yang sedang berjalan) itu memberikan nullpointerexception pada baris "untuk (File file: dir.listFiles ()) {". Beberapa file muncul dan menghilang dengan cepat di folder hidup. Jadi saya menambahkan cek null untuk nilai kembali dir.listFiles () sebelum for loop.
csonuryilmaz
Dari File.listFiles () javadoc: "Array akan kosong jika direktorinya kosong. Mengembalikan null jika nama path abstrak ini tidak menunjukkan direktori, atau jika terjadi kesalahan I / O." Jadi komentar di atas berguna saat mendapatkan ukuran folder pada folder yang berubah secara dinamis.
csonuryilmaz
7

Untuk Java 8 ini adalah salah satu cara yang tepat untuk melakukannya:

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

Penting untuk memfilter semua direktori , karena metode panjang tidak dijamin 0 untuk direktori.

Setidaknya kode ini memberikan informasi ukuran yang sama seperti yang dilakukan Windows Explorer itu sendiri.

wumpz.dll
sumber
4

Berikut cara terbaik untuk mendapatkan ukuran File umum (berfungsi untuk direktori dan non-direktori):

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

Sunting: Perhatikan bahwa ini mungkin akan menjadi operasi yang memakan waktu. Jangan menjalankannya di thread UI.

Selain itu, di sini (diambil dari https://stackoverflow.com/a/5599842/1696171 ) adalah cara yang bagus untuk mendapatkan String yang dapat dibaca pengguna dari yang sudah lama dikembalikan:

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];
}
Eric Cochran
sumber
4

Jika Anda ingin menggunakan Java 8 NIO API, program berikut akan mencetak ukuran, dalam byte, dari direktori tempatnya berada.

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

}

The calculateSizemetode adalah universal untuk Pathobjek, sehingga ia juga bekerja untuk file. Perhatikan bahwa jika file atau direktori tidak dapat diakses, dalam hal ini ukuran yang dikembalikan dari objek jalur adalah 0.

dinomario10
sumber
3

File.length()( Javadoc ).

Perhatikan bahwa ini tidak berfungsi untuk direktori, atau tidak dijamin akan berhasil.

Untuk direktori, apa yang Anda inginkan? Jika itu adalah ukuran total semua file di bawahnya, Anda dapat secara rekursif menuntun anak-anak menggunakan File.list()dan File.isDirectory()dan menjumlahkan ukurannya.

danben
sumber
3

The Fileobjek memiliki lengthmetode:

f = new File("your/file/name");
f.length();
JesperE
sumber
3
  • Bekerja untuk Android dan Java
  • Berfungsi untuk folder dan file
  • Memeriksa penunjuk nol di mana pun jika diperlukan
  • Mengabaikan tautan simbolik alias pintasan
  • Produksi siap!

Kode sumber:

   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());
    }
Ilya Gazman
sumber
1

untuk windows, menggunakan java.io fungsi rekursif ini berguna.

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

Ini diuji dan berfungsi dengan baik di pihak saya.

Ini PD
sumber
1

Saya telah menguji du -c <folderpath>dan 2x lebih cepat dari nio.File atau rekursi

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;
}
G Dias
sumber
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;
    }
Nicholas
sumber
0

Setelah banyak meneliti dan mencari solusi berbeda yang diusulkan di sini di StackOverflow. Saya akhirnya memutuskan untuk menulis solusi saya sendiri. Tujuan saya adalah memiliki mekanisme no-throw karena saya tidak ingin crash jika API tidak dapat mengambil ukuran folder. Metode ini tidak cocok untuk skenario mult-threaded.

Pertama-tama saya ingin memeriksa direktori yang valid saat menelusuri pohon sistem file.

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

Kedua, saya tidak ingin panggilan rekursif saya masuk ke symlink (tautan lunak) dan menyertakan ukuran dalam agregat 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());
}

Akhirnya implementasi berbasis rekursi saya untuk mengambil ukuran direktori yang ditentukan. Perhatikan pemeriksaan null untuk dir.listFiles (). Menurut javadoc ada kemungkinan metode ini dapat mengembalikan 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;
    }
}

Beberapa krim kue, API untuk mendapatkan ukuran file daftar (mungkin semua file dan folder di bawah root).

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

di linux jika Anda ingin mengurutkan direktori, maka du -hs * | urutkan -h

Prem S
sumber
0

Anda dapat menggunakan Apache Commons IOuntuk mencari ukuran folder dengan mudah.

Jika Anda menggunakan maven, silakan tambahkan ketergantungan berikut di pom.xmlfile Anda .

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

Jika bukan penggemar Maven, unduh jar berikut dan tambahkan ke jalur kelas.

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
}

Untuk mendapatkan ukuran file melalui Commons IO,

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

long fileSize = FileUtils.sizeOf(file);

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

Itu juga dapat dicapai melalui Google Guava

Untuk Maven, tambahkan yang berikut ini:

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

Jika tidak menggunakan Maven, tambahkan berikut ini ke jalur kelas

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

Untuk mendapatkan ukuran file,

 File file = new File("PATH TO YOUR FILE");
 long s  = file.length();
 System.out.println(s);
Dulith De Costa
sumber
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;
        }
Jaskaran Singh
sumber
Meskipun kode Anda terlihat bagus, saya tidak yakin itu menambahkan apa pun ke jawaban lain. Jika ya, harap edit jawaban Anda untuk menjelaskan.
Dragonthoughts
Ini hanya versi terbaru dari melakukan pekerjaan yang sama dalam lebih sedikit baris kode.
Jaskaran Singh