‘壹’ android中如何获得外置sd卡的路径和手机自身内存的路径
你问的编码?
原文:http://blog.163.com/hero_213/blog/static/39891214201162123236660/
转载非原创。
该代码片段可以让我们获取internal和external的存储空间大小。
import java.io.File;
import android.os.Environment;
import android.os.StatFs;
public class StorageUtil {
private static final int ERROR = -1;
/**
* SDCARD是否存
*/
public static boolean externalMemoryAvailable() {
return android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED);
}
/**
* 获取手机内部剩余存储空间
* @return
*/
public static long () {
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks * blockSize;
}
/**
* 获取手机内部总的存储空间
* @return
*/
public static long getTotalInternalMemorySize() {
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
return totalBlocks * blockSize;
}
/**
* 获取SDCARD剩余存储空间
* @return
*/
public static long () {
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;
}
}
/**
* 获取SDCARD总的存储空间
* @return
*/
public static 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;
}
}
}
1.硬件上的 block size, 应该是"sector size",linux的扇区大小是512byte
2.有文件系统的分区的block size, 是"block size",大小不一,可以用工具查看
3.没有文件系统的分区的block size,也叫“block size”,大小指的是1024 byte
4.Kernel buffer cache 的block size, 就是"block size",大部分PC是1024
5.磁盘分区的"cylinder size",用fdisk 可以查看。
我们这里的block size是第二种情况,一般SD卡都是fat32的文件系统,block size是4096.
这样就可以知道手机的内部存储空间和sd卡存储空间的总大小和可用大小了。
‘贰’ 和df统计的磁盘分区大小不一致
Linux下查看磁盘空间使用情况,最常使用的是和df。有一次和df统计的磁盘分区大小不一致,这是为什么呢?二者有什么区别?网上搜索下,大神早有总结,实践后汇总学习下。
对待统计文件逐个系统调用fstat,获取文件大小。它的数据是基于文件获取的,所以有很大的灵活性,不一定非要针对一个分区,可以跨越多个分区操作。如果针对的目录中文件很多,速度就会很慢了。
1.如果统计目录下挂载了其他文件系统,那么也会对这个文件系统进行统计。计算时记得将这一部分从总和中去掉。
2.如果文件被删除,即使被其他进程引用了,命令也无法对其统计。因为stat命令找不到这个文件。
3.可以跨分区统计某些你想统计的文件大小总和。因为它们都能被stat找到并统计。
df使用系统调用statfs,直接读取分区的超级块superblock信息来获取分区使用情况。它的数据是基于分区元数据的,所以只能针对整个分区。由于df直接读取超级块(superblock才占用1024字节),所以运行速度不受文件多少影响。
1. 当某个文件系统下挂载了其他分区,df不会把这个分区也统计进去。
因为df读取的是各自分区的superblock,即使分区1挂载在分区0的目录下,df统计分区0的时候,也只能读取分区0的superblock。
2.由于df每次统计都是读取superblock,所以df对文件系统中的 某个文件 进行统计时,会自动转为统计这个 文件系统(分区)的信息 。 也就是说,df通过文件找到对应的分区挂载点。
[root@xuexi ~]# df -hT /etc/fstab
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda2 ext4 18G 1.7G 15G 11% /
3. df会统计因子挂载点而被隐藏的原目录文件大小。
如果在/mnt目录下有3G的文件,然后在/mnt上挂载了其他文件系统,/mnt下原本那3G的文件就被隐藏起来无法访问,无法统计这部分数据大小(但会统计挂载在/mnt上的文件),但df会统计这部分信息。
4.df会统计已删除但却仍有进程引用的文件。
正常情况下,删除文件会立刻释放相关指针,并将imap和bmap中相关的位图标记为未使用。bmap只要一改变,文件系统立刻就能知道每个块组中哪些数据块是空闲的,哪些数据块是被使用的,这些信息都会更新到分区的superblock中。于是df能立刻统计到实时的磁盘空间信息。读写文件的过程以及涉及的imap和bmap,后面再研究。
常见的df和不一致情况是文件删除的问题。当一个文件被删除后,在文件系统目录中已经不可见了,所以就不再统计它。然而如果此时还有运行的进程持有这个已经被删除文件的句柄,这个文件就不会真正在磁盘中被删除, 分区超级块中的信息也就不会更改。这样df仍旧会统计这个被删除了的文件。
在home下创建一个1G大小的文件test.log,df -h /home和 -sh --max-depth=1 /home查看磁盘空间占用情况。
tail -f test.log &,然后rm -rf test.log。
# lsof | grep test.log
tail 23955 root 3r REG 8,1 1048576000 7999 /home/test.log (deleted)
使用df -h /home和 -sh --max-depth=1 /home再次查看磁盘空间占用情况。发现df没有变化,而则不再统计被删除了的文件test.log。
停止进程23955,使用df和再次查看,数据一致了。
是用户级的程序,它不考虑Meta Data,而df命令则查看文件系统的磁盘分配图并考虑Meta Data。df命令获得真正的文件系统数据,而命令只查看文件系统的部分情况。
df和显示的磁盘空间使用情况不一致的原因及处理
详细分析和df的统计结果为什么不一样