2010-01-27 197 views
87

如何檢索Java中的文件夾或文件的大小?獲取文件夾或文件的大小

+0

相同,但與注重效率:http://stackoverflow.com/questions/116574/java-get-file-size-efficiently – 2015-03-02 03:14:14

回答

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

這將返回該文件的以字節爲單位的長度或0如果該文件不存在。沒有內置的方法來獲取文件夾的大小,您將不得不遞歸地遍歷目錄樹(使用表示目錄的文件對象的listFiles()方法)併爲自己積累目錄大小:

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

警告:該方法對於生產使用不夠穩健。 directory.listFiles()可能會返回null並導致NullPointerException。此外,它不考慮符號鏈接並可能有其他失敗模式。使用this method

+19

+1這樣的準備運行示例 – stacker 2010-01-27 20:31:18

+11

如果在Windows計算機的C:根目錄中運行此操作,請小心;有一個系統文件(根據java.io.File)既不是文件也不是目錄。您可能想要更改else子句來檢查文件實際上是一個目錄。 – 2010-01-27 22:50:45

+2

簡單的改變來檢查參數,看它是否不是方法開始處的目錄,並返回長度,然後遞歸更簡單 - 只需將該調用添加到同一方法中的self,然後這支持傳入文件引用而不是目錄。 – 2010-01-28 07:48:33

3

File.length()Javadoc)。

請注意,這不適用於目錄,或不能保證工作。

對於一個目錄,你想要什麼?如果它是其下的所有文件的總大小,則可以使用File.list()File.isDirectory()遞歸地走孩子,並對它們的大小進行求和。

3

File對象具有length方法:

f = new File("your/file/name"); 
f.length(); 
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你的代碼需要有一個簡單的修復,在遞歸調用中,你應該將大小添加到現有大小不只是分配給它。 'size + = getFolderSize(file);' – 2010-01-27 19:51:53

+0

@Teja:感謝您指出,但是這些更改也將在if語句中 – Vishal 2010-01-27 20:54:52

+0

有時在*增長文件夾(另一個線程正在下載文件和文件夾)同時我正在打印文件夾大小的進展)它提供了** nullpointerexception **在行「for(File file:dir.listFiles()){」。有些文件在活文件夾上快速出現和消失。所以我在for循環之前爲* dir.listFiles()*返回值添加了空檢查。 – csonuryilmaz 2017-05-27 13:26:28

29

您需要FileUtils#sizeOfDirectory(File)commons-io

請注意,您將需要手動檢查該文件是否爲目錄,因爲如果將非目錄傳遞給該目錄,該方法會引發異常。

警告:此方法(自commons-io 2.4開始)有一個錯誤,如果同時修改目錄,則可能拋出IllegalArgumentException

+0

那麼當文件不是目錄時會發生什麼?當它不存在? etc - 文件有多糟糕 – 2013-09-20 22:31:01

+0

@Mr_and_Mrs_D - 只需複製並粘貼'checkDirectory(directory); check'後面的行。只要確保'File.listFiles'有孩子。 **參考:** [FileUtils.sizeOfDirectory()](http://grepcode.com/file/repo1.maven.org/maven2/commons-io/commons-io/2.4/org/apache/commons/io/ FileUtils.java#FileUtils.sizeOfDirectory%28java.io.File%29),[File.listFiles()](http://docs.oracle.com/javase/6/docs/api/java/io/File.html #listFiles) – 2014-07-15 01:02:30

+2

查看bug [IO-449](https://issues.apache.org/jira/browse/IO-449)。如果該目錄在迭代過程中被修改,該方法將拋出'IllegalArgumentException'。 – 2015-10-28 10:14:49

27

使用java-7 nio api,計算文件夾大小可以快得多。

這是一個可以運行的示例,它是健壯的,不會拋出異常。它會記錄它無法進入的目錄或遇到問題遍歷。符號鏈接將被忽略,並且目錄的併發修改不會導致比所需更多的麻煩。

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

在Android開發中是否有這樣的等價物? – 2014-04-30 22:23:34

+0

是否有使用'AtomicLong'而不只是'long'的理由? – 2014-12-27 19:25:54

+0

從匿名類訪問時,變量必須是最終的 – 2014-12-28 10:30:57

8

在Java 8:

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

這將是更好的地圖一步使用Files::size但它拋出一個checked異常。

更新:
您還應該知道,如果某些文件/文件夾不可訪問,這可能會引發異常。請參閱此question以及使用Guava的另一個解決方案。

+1

我正在尋找類似的東西,並以代碼問題結束:http://stackoverflow.com/questions/22867286/ files-walk-calculate-total-size,正如你所看到的,錯誤處理的另一個方面也會導致問題。 – 2014-07-15 07:39:17

+0

@AkselWillgert謝謝,這是不幸的,我已經更新了答案。現在切換到番石榴http://stackoverflow.com/a/24757556/1180621 – Andrejs 2014-07-15 11:53:29

2

這裏得到一個普通文件的大小(適用於目錄和非目錄)的最佳方式:

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

編輯:請注意,這很可能將是一個耗時的操作。不要在UI線程上運行它。

另外,這裏(從https://stackoverflow.com/a/5599842/1696171拍攝)是一個很好的方式來獲得長期返回用戶可讀的字符串:

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

大量的研究和尋找到不同的解決方案後,這裏提出的堆棧溢出。我終於決定寫我自己的解決方案。我的目的是具有無投擲機制,因爲如果API無法獲取文件夾大小,我不想崩潰。 此方法不適用於多線程場景。

首先,我想在遍歷文件系統樹時檢查有效的目錄。

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

第二我不希望我的遞歸調用進入符號鏈接(軟鏈接),幷包括在總的聚合中的大小。

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

最後我的基於遞歸的實現來獲取指定目錄的大小。注意dir.listFiles()的空檢查。根據javadoc,這種方法有可能返回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; 
    } 
} 

一些奶油蛋糕,獲取列表大小的API文件(可能是根目錄下的所有文件和文件夾)。

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

對於的Java 8這是做一個正確的方法:

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

它過濾掉所有目錄是很重要的,因爲長度的方法不能保證爲0爲目錄。

至少這個代碼提供像Windows資源管理器本身一樣的大小信息。

2

如果你想使用的Java 8 NIO API,下面的程序將打印大小,以字節爲單位,它位於目錄。

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

} 

calculateSize方法是萬能的Path對象,所以它也適用於文件。 注意如果文件或目錄是不可訪問的,在這種情況下路徑對象的返回大小將是0

0

如果你想對目錄進行排序然後du -hs * |排序-h

1
  • Works爲的Android的Java
  • 同時適用於文件夾和文件
  • 檢查的空指針無處不在需要的地方
  • 忽略symbolic link又名快捷鍵
  • 生產做好準備!

的源代碼:

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