2010-10-28 435 views

回答

35

剛經過的所有文件,總結它們的長度:

/** 
* Return the size of a directory in bytes 
*/ 
private static long dirSize(File dir) { 

    if (dir.exists()) { 
     long result = 0; 
     File[] fileList = dir.listFiles(); 
     for(int i = 0; i < fileList.length; i++) { 
      // Recursive call if it's a directory 
      if(fileList[i].isDirectory()) { 
       result += dirSize(fileList [i]); 
      } else { 
       // Sum the file size in bytes 
       result += fileList[i].length(); 
      } 
     } 
     return result; // return the file size 
    } 
    return 0; 
} 

注:手寫功能,因此無法編譯!

編輯:遞歸調用固定。

EDITED:dirList.length改爲fileList.length。

+0

你可能想用dirSize替換findFile :) – 2010-10-28 08:23:13

+0

我建議用'dir.isDirectory()'替換'dir.exists()'。如果給定一個文件作爲參數NullPointerException由於listFiles()結果而被拋出。 – 2013-12-20 17:14:35

+0

@Moss「for-each」循環更好,就像谷歌在http://developer.android.com/training/articles/perf-tips.html#Loops – 2015-02-23 15:13:46

0

遍歷所有文件的代碼少於5行,這是唯一合理的方法。如果你想變得醜陋,你也可以運行系統命令(調用Runtime.getRuntime()EXEC(「杜」);),趕上輸出;)

+1

不夠公平。只是認爲這是一個常見的用例,應該有一些本地解決方案。懶惰很好......五行後,我很高興:) – 2010-10-28 08:38:17

+0

在Clojure中:(defn dir-size [dir](reduce +(map#(。length%)(.listFiles(new File dir))) )) – 2010-10-28 12:19:06

+0

我不認爲依靠可用和可執行文件是安全的。 – 2011-03-14 11:04:31

5
/** 
* Try this one for better performance 
* Mehran 
* Return the size of a directory in bytes 
**/ 

private static long dirSize(File dir) { 
    long result = 0; 

    Stack<File> dirlist= new Stack<File>(); 
    dirlist.clear(); 

    dirlist.push(dir); 

    while(!dirlist.isEmpty()) 
    { 
     File dirCurrent = dirlist.pop(); 

     File[] fileList = dirCurrent.listFiles(); 
     for(File f: fileList){ 
      if(f.isDirectory()) 
       dirlist.push(f); 
      else 
       result += f.length(); 
     } 
    } 

    return result; 
} 
+2

由於我們正在討論文件操作,遞歸不太可能解決很多性能問題。另外,java.util.Stack實現非常慢。我試圖用它優化遞歸算法,然後讓JVM執行它的工作實際上比較慢。 – 2011-12-12 05:21:02

+0

java.util.Stack類方法已同步。如果你真的想避免遞歸,最好使用LinkedList。 – 2013-02-12 14:06:00

1

以下方法返回文件夾的大小,你 -

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

調用上述方法: -

File file = new File(Environment.getExternalStorageDirectory().getPath()+"/urfoldername/"); 

long folder_size=getFolderSize(file); 

回報你的文件夾的大小。

3

#Moss的方式是對的。這是我希望將字節更改爲可讀格式的代碼。你只需要到指定文件夾的路徑dirSize(String path)並獲得基於字節,千,萬和人類可讀的格式等

private static String dirSize(String path) { 

     File dir = new File(path); 

     if(dir.exists()) { 
      long bytes = getFolderSize(dir); 
      if (bytes < 1024) return bytes + " B"; 
      int exp = (int) (Math.log(bytes)/Math.log(1024)); 
      String pre = ("KMGTPE").charAt(exp-1) + ""; 

      return String.format("%.1f %sB", bytes/Math.pow(1024, exp), pre); 
     } 

     return "0"; 
    } 

    public static long getFolderSize(File dir) { 
     if (dir.exists()) { 
      long result = 0; 
      File[] fileList = dir.listFiles(); 
      for(int i = 0; i < fileList.length; i++) { 
       // Recursive call if it's a directory 
       if(fileList[i].isDirectory()) { 
        result += getFolderSize(fileList[i]); 
       } else { 
        // Sum the file size in bytes 
        result += fileList[i].length(); 
       } 
      } 
      return result; // return the file size 
     } 
     return 0; 
    } 
2

問題的其他解決辦法是,他們爲您提供在指定的所有文件的唯一合乎邏輯的大小目錄。它將與實際(物理)已用空間不同。如果你的目錄有很多子目錄和/或小文件,那麼目錄的邏輯和實際大小可能會有很大的差異。

以下是我發現如何計算FS的物理結構。

public static long getDirectorySize(File directory, long blockSize) { 
    File[] files = directory.listFiles(); 
    if (files != null) { 

     // space used by directory itself 
     long size = file.length(); 

     for (File file : files) { 
      if (file.isDirectory()) { 
       // space used by subdirectory 
       size += getDirectorySize(file, blockSize); 
      } else { 
       // file size need to rounded up to full block sizes 
       // (not a perfect function, it adds additional block to 0 sized files 
       // and file who perfectly fill their blocks) 
       size += (file.length()/blockSize + 1) * blockSize; 
      } 
     } 
     return size; 
    } else { 
     return 0; 
    } 
} 

您可以使用StatFs得到的塊大小:

public static long getDirectorySize(File directory) { 
    StatFs statFs = new StatFs(directory.getAbsolutePath()); 
    long blockSize; 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 
     blockSize = statFs.getBlockSizeLong() 
    } else { 
     blockSize = statFs.getBlockSize(); 
    } 

    return getDirectorySize(directory, blockSize); 
} 
+0

我注意到如果我在目錄上調用「length()」,我不會得到0,而是一個實數。是否有可能不使用你已經做過的事情,而只是在目錄上使用「length()」(當然還有剩下的事情 - 增加普通文件的大小)? – 2014-04-30 22:10:05

5

您應使用此代碼:

public static long getFolderSize(File f) { 
    long size = 0; 
    if (f.isDirectory()) { 
     for (File file : f.listFiles()) {  
      size += getFolderSize(file); 
     } 
    } else { 
     size=f.length(); 
    } 
    return size; 
} 
+0

偉大的解決方案,我有一個文件夾與一些音頻文件,它的作品perfekt對我來說! (我在這個文件夾中沒有子文件夾!) – basti12354 2015-04-04 15:17:39

11

下面是一些代碼,避免了遞歸,並且還計算物理大小,而不是的邏輯大小:

public static long getFileSize(final File file) { 
    if (file == null || !file.exists()) 
     return 0; 
    if (!file.isDirectory()) 
     return file.length(); 
    final List<File> dirs = new LinkedList<>(); 
    dirs.add(file); 
    long result = 0; 
    while (!dirs.isEmpty()) { 
     final File dir = dirs.remove(0); 
     if (!dir.exists()) 
      continue; 
     final File[] listFiles = dir.listFiles(); 
     if (listFiles == null || listFiles.length == 0) 
      continue; 
     for (final File child : listFiles) { 
      result += child.length(); 
      if (child.isDirectory()) 
       dirs.add(child); 
     } 
    } 
    return result; 
} 
+0

這是計算文件/文件夾大小的絕對正確答案 – 2014-05-08 13:43:51

+0

我真的很驚訝地看到(在Android上)每個文件夾大約需要4KB,即使它是空的。想知道他們爲什麼這樣做。 – 2014-05-08 15:07:58

+0

@androiddeveloper它是扇區大小。您會注意到,在任何桌面操作系統上都是如此。 – 2017-07-10 11:36:50

0

您可以在MediaStore上查詢內部存儲上的目錄大小。這比獲取目錄中每個文件長度的遞歸方法快得多。您必須擁有READ_EXTERNAL_STORAGE許可。

實施例:

/** 
* Query the media store for a directory size 
* 
* @param context 
*  the application context 
* @param file 
*  the directory on primary storage 
* @return the size of the directory 
*/ 
public static long getFolderSize(Context context, File file) { 
    File directory = readlink(file); // resolve symlinks to internal storage 
    String path = directory.getAbsolutePath(); 
    Cursor cursor = null; 
    long size = 0; 
    try { 
    cursor = context.getContentResolver().query(MediaStore.Files.getContentUri("external"), 
     new String[]{MediaStore.MediaColumns.SIZE}, 
     MediaStore.MediaColumns.DATA + " LIKE ?", 
     new String[]{path + "/%/%"}, 
     null); 
    if (cursor != null && cursor.moveToFirst()) { 
     do { 
     size += cursor.getLong(0); 
     } while (cursor.moveToNext()); 
    } 
    } finally { 
    if (cursor != null) { 
     cursor.close(); 
    } 
    } 
    return size; 
} 

/** 
* Canonicalize by following all symlinks. Same as "readlink -f file". 
* 
* @param file 
*  a {@link File} 
* @return The absolute canonical file 
*/ 
public static File readlink(File file) { 
    File f; 
    try { 
    f = file.getCanonicalFile(); 
    } catch (IOException e) { 
    return file; 
    } 
    if (f.getAbsolutePath().equals(file.getAbsolutePath())) { 
    return f; 
    } 
    return readlink(f); 
} 

用法:

File DCIM = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); 
long directorySize = getFolderSize(context, DCIM); 
String formattedSize = Formatter.formatFileSize(context, directorySize); 
System.out.println(DCIM + " " + formattedSize); 

輸出:

/存儲/模擬/ 0/DCIM 30.86 MB

相關問題