如何查找 Android 上剩余的可用存储空间(磁盘空间)? [复制]
Posted
技术标签:
【中文标题】如何查找 Android 上剩余的可用存储空间(磁盘空间)? [复制]【英文标题】:How to find the amount of free storage (disk space) left on Android? [duplicate] 【发布时间】:2011-10-30 05:03:09 【问题描述】:我正在尝试找出运行我的应用程序的 android 手机上的可用磁盘空间。有没有办法以编程方式做到这一点?
谢谢,
【问题讨论】:
以重复形式关闭 - 较新的帖子可以回答 Android R 【参考方案1】:示例:获得人类可读的大小,例如 1 Gb
字符串内存 = bytesToHuman(totalMemory())
/*************************************************************************************************
Returns size in bytes.
If you need calculate external memory, change this:
StatFs statFs = new StatFs(Environment.getRootDirectory().getAbsolutePath());
to this:
StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());
**************************************************************************************************/
public long totalMemory()
StatFs statFs = new StatFs(Environment.getRootDirectory().getAbsolutePath());
long total = (statFs.getBlockCount() * statFs.getBlockSize());
return total;
public long freeMemory()
StatFs statFs = new StatFs(Environment.getRootDirectory().getAbsolutePath());
long free = (statFs.getAvailableBlocks() * statFs.getBlockSize());
return free;
public long busyMemory()
StatFs statFs = new StatFs(Environment.getRootDirectory().getAbsolutePath());
long total = (statFs.getBlockCount() * statFs.getBlockSize());
long free = (statFs.getAvailableBlocks() * statFs.getBlockSize());
long busy = total - free;
return busy;
将字节转换为人类可读的格式(如 1 Mb、1 Gb)
public static String floatForm (double d)
return new DecimalFormat("#.##").format(d);
public static String bytesToHuman (long size)
long Kb = 1 * 1024;
long Mb = Kb * 1024;
long Gb = Mb * 1024;
long Tb = Gb * 1024;
long Pb = Tb * 1024;
long Eb = Pb * 1024;
if (size < Kb) return floatForm( size ) + " byte";
if (size >= Kb && size < Mb) return floatForm((double)size / Kb) + " Kb";
if (size >= Mb && size < Gb) return floatForm((double)size / Mb) + " Mb";
if (size >= Gb && size < Tb) return floatForm((double)size / Gb) + " Gb";
if (size >= Tb && size < Pb) return floatForm((double)size / Tb) + " Tb";
if (size >= Pb && size < Eb) return floatForm((double)size / Pb) + " Pb";
if (size >= Eb) return floatForm((double)size / Eb) + " Eb";
return "???";
【讨论】:
getAvailableBlocks()
和 getBlockSize()
已被弃用并分别替换为 getAvailableBlocksLong()
和 statFs.getBlockSizeLong()
。
Environment.getRootDirectory() 表示您正在查询系统/操作系统分区的总、空闲和忙碌内存。要获取应用程序可用内存的统计信息,您应该查询数据分区。见***.com/a/35512682/483708。【参考方案2】:
试试StatFs.getAvailableBlocks。您需要使用 getBlockSize 将块数转换为 KB。
【讨论】:
对于 API 级别 >= 18 - StatFs.getAvailableBytes () 返回文件系统上空闲且可供应用程序使用的字节数。 getAvailableBlocks 已被 api 级别 18 弃用,新方法是 getAvailableBlocksLong【参考方案3】:关于当前答案都没有解决的路径存在一些微妙之处。您必须根据您感兴趣的统计数据类型使用正确的路径。基于对 DeviceStorageMonitorService.java 的深入研究,它会在通知区域中生成磁盘空间不足警告以及 ACTION_DEVICE_STORAGE_LOW 的粘性广播,以下是一些路径你可以使用:
要检查可用的内部磁盘空间,请使用通过 Environment.getDataDirectory() 获得的数据目录。这将为您提供数据分区上的可用空间。数据分区托管设备上所有应用的所有内部存储。
要检查可用的外部 (SDCARD) 磁盘空间,请使用通过 Environment.getExternalStorageDirectory() 获得的外部存储目录。这将为您提供 SDCARD 上的可用空间。
要检查包含操作系统文件的系统分区上的可用内存,请使用 Environment.getRootDirectory()。由于您的应用程序无法访问系统分区,因此此统计信息可能不是很有用。 DeviceStorageMonitorService 用于提供信息并将其输入日志。
要检查临时文件/缓存内存,请使用 Environment.getDownloadCacheDirectory()。 DeviceStorageMonitorService 会在内存不足时尝试清理一些临时文件。
一些获取内部(/data)、外部(/sdcard)和操作系统(/system)空闲内存的示例代码:
// Get internal (data partition) free space
// This will match what's shown in System Settings > Storage for
// Internal Space, when you subtract Total - Used
public long getFreeInternalMemory()
return getFreeMemory(Environment.getDataDirectory());
// Get external (SDCARD) free space
public long getFreeExternalMemory()
return getFreeMemory(Environment.getExternalStorageDirectory());
// Get Android OS (system partition) free space
public long getFreeSystemMemory()
return getFreeMemory(Environment.getRootDirectory());
// Get free space for provided path
// Note that this will throw IllegalArgumentException for invalid paths
public long getFreeMemory(File path)
StatFs stats = new StatFs(path.getAbsolutePath());
return stats.getAvailableBlocksLong() * stats.getBlockSizeLong();
【讨论】:
你总结得很好,但是 getAvailableBlocks() 和 getBlockSize() 这两个方法都被弃用了。请更新您的答案。【参考方案4】:根据@XXX 的回答,我创建了一个包含 StatFs 的要点代码 sn-p,以便于使用。 你可以找到它here as a GitHub gist。
【讨论】:
【参考方案5】:在进行乘法之前将您的整数值类型转换为 long。两个大整数之间的乘法可能会溢出并给出否定结果。
public long sd_card_free()
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs(path.getPath());
int availBlocks = stat.getAvailableBlocksLong();
int blockSize = stat.getBlockSizeLong();
long free_memory = (long)availBlocks * (long)blockSize;
return free_memory;
【讨论】:
+1 这大概就是为什么getAvailableBlocks()
和getBlockSize()
被getAvailableBlocksLong()
和statFs.getBlockSizeLong()
取代的原因。
从一开始就更好地为availBlocks和blockSize使用长变量。【参考方案6】:
用一点谷歌你可能已经找到了StatFs
-class,它是:
[...] Unix statfs() 的包装器。
例如here 和这里:
import java.io.File;
import android.os.Environment;
import android.os.StatFs;
public class MemoryStatus
static final int ERROR = -1;
static public boolean externalMemoryAvailable()
return android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
static public long getAvailableInternalMemorySize()
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks * blockSize;
static public long getTotalInternalMemorySize()
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
return totalBlocks * blockSize;
static public long getAvailableExternalMemorySize()
if(externalMemoryAvailable())
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks * blockSize;
else
return ERROR;
static public long getTotalExternalMemorySize()
if(externalMemoryAvailable())
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
return totalBlocks * blockSize;
else
return ERROR;
static public String formatSize(long size)
String suffix = null;
if (size >= 1024)
suffix = "KiB";
size /= 1024;
if (size >= 1024)
suffix = "MiB";
size /= 1024;
StringBuilder resultBuffer = new StringBuilder(Long.toString(size));
int commaOffset = resultBuffer.length() - 3;
while (commaOffset > 0)
resultBuffer.insert(commaOffset, ',');
commaOffset -= 3;
if (suffix != null)
resultBuffer.append(suffix);
return resultBuffer.toString();
Source for code above (Wayback Machine)
【讨论】:
第二个链接坏了 @youravgjoe 用 Wayback Machine 找回了它。【参考方案7】: File pathOS = Environment.getRootDirectory();//Os Storage
StatFs statOS = new StatFs(pathOS.getPath());
File pathInternal = Environment.getDataDirectory();// Internal Storage
StatFs statInternal = new StatFs(pathInternal.getPath());
File pathSdcard = Environment.getExternalStorageDirectory();//External(SD CARD) Storage
StatFs statSdcard = new StatFs(pathSdcard.getPath());
if((android.os.Build.VERSION.SDK_INT < 18))
// Get Android OS (system partition) free space API 18 & Below
int totalBlocksOS = statOS.getBlockCount();
int blockSizeOS = statOS.getBlockSize();
int availBlocksOS = statOS.getAvailableBlocks();
long total_OS_memory = (long) totalBlocksOS * (long) blockSizeOS;
long free_OS_memory = (long) availBlocksOS * (long) blockSizeOS;
long Used_OS_memory = total_OS_memory - free_OS_memory;
TotalOsMemory = total_OS_memory ;
FreeOsMemory = free_OS_memory;
UsedOsMemory = Used_OS_memory;
// Get internal (data partition) free space API 18 & Below
int totalBlocksInternal = statInternal.getBlockCount();
int blockSizeInternal = statOS.getBlockSize();
int availBlocksInternal = statInternal.getAvailableBlocks();
long total_Internal_memory = (long) totalBlocksInternal * (long) blockSizeInternal;
long free_Internal_memory = (long) availBlocksInternal * (long) blockSizeInternal;
long Used_Intenal_memory = total_Internal_memory - free_Internal_memory;
TotalInternalMemory = total_Internal_memory;
FreeInternalMemory = free_Internal_memory ;
UsedInternalMemory = Used_Intenal_memory ;
// Get external (SDCARD) free space for API 18 & Below
int totalBlocksSdcard = statSdcard.getBlockCount();
int blockSizeSdcard = statOS.getBlockSize();
int availBlocksSdcard = statSdcard.getAvailableBlocks();
long total_Sdcard_memory = (long) totalBlocksSdcard * (long) blockSizeSdcard;
long free_Sdcard_memory = (long) availBlocksSdcard * (long) blockSizeSdcard;
long Used_Sdcard_memory = total_Sdcard_memory - free_Sdcard_memory;
TotalSdcardMemory = total_Sdcard_memory;
FreeSdcardMemory = free_Sdcard_memory;
UsedSdcardMemory = Used_Sdcard_memory;
else
// Get Android OS (system partition) free space for API 18 & Above
long total_OS_memory = (statOS. getBlockCountLong() * statOS.getBlockSizeLong());
long free_OS_memory = (statOS. getAvailableBlocksLong() * statOS.getBlockSizeLong());
long Used_OS_memory = total_OS_memory - free_OS_memory;
TotalOsMemory = total_OS_memory ;
FreeOsMemory = free_OS_memory;
UsedOsMemory = Used_OS_memory;
// Get internal (data partition) free space for API 18 & Above
long total_Internal_memory = (statInternal. getBlockCountLong() * statInternal.getBlockSizeLong());
long free_Internal_memory = (statInternal. getAvailableBlocksLong() * statInternal.getBlockSizeLong());
long Used_Intenal_memory = total_Internal_memory - free_Internal_memory;
TotalInternalMemory = total_Internal_memory;
FreeInternalMemory = free_Internal_memory ;
UsedInternalMemory = Used_Intenal_memory ;
// Get external (SDCARD) free space for API 18 & Above
long total_Sdcard_memory = (statSdcard. getBlockCountLong() * statSdcard.getBlockSizeLong());
long free_Sdcard_memory = (statSdcard. getAvailableBlocksLong() * statSdcard.getBlockSizeLong());
long Used_Sdcard_memory = tota*emphasized text*l_Sdcard_memory - free_Sdcard_memory;
TotalSdcardMemory = total_Sdcard_memory;
FreeSdcardMemory = free_Sdcard_memory;
UsedSdcardMemory = Used_Sdcard_memory;
【讨论】:
private Long TotalOsMemory,FreeOsMemory,UsedOsMemory,TotalInternalMemory,FreeInternalMemory,UsedInternalMemory,TotalSdcardMemory,FreeSdcardMemory,UsedSdcardMemory;【参考方案8】:/**
* Returns the amount of free memory.
* @return @code long - Free space.
*/
public long getFreeInternalMemory()
return getFreeMemory(Environment.getDataDirectory());
/**
* Returns the free amount in SDCARD.
* @return @code long - Free space.
*/
public long getFreeExternalMemory()
return getFreeMemory(Environment.getExternalStorageDirectory());
/**
* Returns the free amount in OS.
* @return @code long - Free space.
*/
public long getFreeSystemMemory()
return getFreeMemory(Environment.getRootDirectory());
/**
* Returns the free amount in mounted path
* @param path @link File - Mounted path.
* @return @code long - Free space.
*/
public long getFreeMemory(File path)
if ((null != path) && (path.exists()) && (path.isDirectory()))
StatFs stats = new StatFs(path.getAbsolutePath());
return stats.getAvailableBlocksLong() * stats.getBlockSizeLong();
return -1;
/**
* Convert bytes to human format.
* @param totalBytes @code long - Total of bytes.
* @return @link String - Converted size.
*/
public String bytesToHuman(long totalBytes)
String[] simbols = new String[] "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB";
long scale = 1L;
for (String simbol : simbols)
if (totalBytes < (scale * 1024L))
return String.format("%s %s", new DecimalFormat("#.##").format((double)totalBytes / scale), simbol);
scale *= 1024L;
return "-1 B";
【讨论】:
【参考方案9】:由于 blocksize 和 getAvailableBlocks
已弃用
这段代码可以用
根据 user802467 的上述回答进行注释
public long sd_card_free()
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs(path.getPath());
long availBlocks = stat.getAvailableBlocksLong();
long blockSize = stat.getBlockSizeLong();
long free_memory = availBlocks * blockSize;
return free_memory;
我们可以使用getAvailableBlocksLong
和getBlockSizeLong
【讨论】:
【参考方案10】:内存位置:
File[] roots = context.getExternalFilesDirs(null);
String path = roots[0].getAbsolutePath(); // PhoneMemory
String path = roots[1].getAbsolutePath(); // SCCard (if available)
String path = roots[2].getAbsolutePath(); // USB (if available)
用法
long totalMemory = StatUtils.totalMemory(path);
long freeMemory = StatUtils.freeMemory(path);
final String totalSpace = StatUtils.humanize(totalMemory, true);
final String usableSpace = StatUtils.humanize(freeMemory, true);
你可以用这个
public final class StatUtils
public static long totalMemory(String path)
StatFs statFs = new StatFs(path);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2)
//noinspection deprecation
return (statFs.getBlockCount() * statFs.getBlockSize());
else
return (statFs.getBlockCountLong() * statFs.getBlockSizeLong());
public static long freeMemory(String path)
StatFs statFs = new StatFs(path);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2)
//noinspection deprecation
return (statFs.getAvailableBlocks() * statFs.getBlockSize());
else
return (statFs.getAvailableBlocksLong() * statFs.getBlockSizeLong());
public static long usedMemory(String path)
long total = totalMemory(path);
long free = freeMemory(path);
return total - free;
public static String humanize(long bytes, boolean si)
int unit = si ? 1000 : 1024;
if (bytes < unit) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
return String.format(Locale.ENGLISH, "%.1f %sB", bytes / Math.pow(unit, exp), pre);
【讨论】:
以上是关于如何查找 Android 上剩余的可用存储空间(磁盘空间)? [复制]的主要内容,如果未能解决你的问题,请参考以下文章