Is it possible to easily get the size of a folder on the SD card? I use a folder for caching of images, and would like to present the total size of all cached images. Is there a way to this other than iterating over each file? They all reside inside the same folder?
问题:
回答1:
Just go through all files and sum the length of them:
/**
* 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;
}
NOTE: Function written by hand so it could not compile!
EDITED: recursive call fixed.
EDITED: dirList.length changed to fileList.length.
回答2:
Here's some code that avoids recursion, and also calculates the physical size instead of the logical size:
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;
}
回答3:
/**
* 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;
}
回答4:
you should use this code:
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;
}
回答5:
The way of #Moss is right. This is my code for those who want to change bytes to human readable format. You just need to assign path of your folder to dirSize(String path)
and get human readable format based on byte, kilo, mega and etc.
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;
}
回答6:
Problem with other solution is that they provide you only logical size of all files in specified directory. It will be different from actual (physical) used space. If your directory has a lot of subdirectories and/or small files, there may be a huge difference between logical and actual size of directory.
Here is what I found how to take in count physical structure of 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;
}
}
You can use StatFs
to get block size:
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);
}
回答7:
below method return you size of folder:-
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;
}
call above method :-
File file = new File(Environment.getExternalStorageDirectory().getPath()+"/urfoldername/");
long folder_size=getFolderSize(file);
return you size of folder.
回答8:
Iterating through all files is less than 5 lines of code and the only reasonable way to do this. If you want to get ugly you could also run a system command (Runtime.getRuntime().exec("du");) and catch the output ;)
回答9:
You can query MediaStore for a directory size on internal storage. This is much faster than a recursive method getting the length of each file in a directory. You must have READ_EXTERNAL_STORAGE
permission granted.
Example:
/**
* 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);
}
Usage:
File DCIM = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
long directorySize = getFolderSize(context, DCIM);
String formattedSize = Formatter.formatFileSize(context, directorySize);
System.out.println(DCIM + " " + formattedSize);
Output:
/storage/emulated/0/DCIM 30.86 MB