Android文件存储:内部存储,外部存储及其路径

Android系统数据存储分为内部存储和外部存储,内部存储是手机系统自带的存储,一般空间都不大,外部存储一般是SD卡的存储,空间一般都比较大。一般我们会把存储内容放在外部存储空间里。在使用过程需要注意事项:

先判断SD卡是否可用,可用时优先使用SD卡的存储,不可用时用内部存储
存储在SD卡上时,可以在SD卡上新建任意一个目录存放,也可以存放在应用程序内部文件夹(APP专属文件),区别是在SD卡的任意目录存放时内容不会随应用程序的卸载而消失,而在应用程序内部的内容会随应用程序卸载消失。
一般缓存文件放在应用程序内部,用户主动保存的文件放在SD卡上的文件夹里。

1.内部存储,外部存储的概念

内部存储
概念:内部存储位于系统中很特殊的一个位置,如果你想将文件存储于内部存储中,那么文件默认只能被你的应用访问到,且一个应用所创建的所有文件都在和应用包名相同的目录下。也就是说应用创建于内部存储的文件,与这个应用是关联起来的。当一个应用卸载之后,内部存储中的这些文件也被删除。从技术上来讲如果你在创建内部存储文件的时候将文件属性设置成可读,其他app能够访问自己应用的数据,前提是他知道你这个应用的包名,如果一个文件的属性是私有(private),那么即使知道包名其他应用也无法访问。 内部存储空间十分有限,因而显得可贵,另外,它也是系统本身和系统应用程序主要的数据存储所在地,一旦内部存储空间耗尽,手机也就无法使用了。所以对于内部存储空间,我们要尽量避免使用。Shared Preferences和SQLite数据库都是存储在内部存储空间上的。

注意内部存储不是内存。内部存储一般用Context来获取和操作。

1、Environment.getDataDirectory().getAbsolutePath() = /data
这个方法是获取内部存储的根路径
2、getFilesDir().getAbsolutePath() = /data/user/0/packname/files
这个方法是获取某个应用在内部存储中的files路径
3、getCacheDir().getAbsolutePath() = /data/user/0/packname/cache
这个方法是获取某个应用在内部存储中的cache路径
4、getDir(“filePath”, MODE_PRIVATE).getAbsolutePath() = /data/user/0/packname/filePath
这个方法是获取某个应用在内部存储中的自定义路径
其中方法2,3,4的路径中都带有包名,说明他们是属于某个应用

Environment.getDataDirectory().getAbsolutePath()   /data 
getCacheDir().getAbsolutePath()   		   /data/user/0/packageName/cache  
getFilesDir().getAbsolutePath()   	           /data/user/0/packageName/files 
getDir(“filePath”, MODE_PRIVATE).getAbsolutePath()    /data/user/0/packageName/files/filePath 

外部存储
概念:对于早期Android 的系统手机自身带的存储卡就是内部存储,而扩展的SD卡就是外部存储。但是随着Android系统的不断升级,从4.4的系统开始,大部分都将机身存储扩展到了8G以上,那么这个是内部存储吗,不是的!!!,它们依然是外部存储,也就是说4.4系统及以上的手机将机身存储存储(手机自身带的存储叫做机身存储)在概念上分成了”内部存储internal” 和”外部存储external” 两部分。既然是外部存储,那有人又有疑惑了,那4.4系统及以上的手机要是插了SD卡呢,SD卡又是什么呢,如果SD卡也是外部存储的话,那怎么区分机身存储的外部存储跟SD卡的外部存储呢?对,SD卡也是外部存储,那怎么区分呢,在4.4以后的系统中,API提供了这样一个方法getExternalFilesDirs(Environment.MEDIA_MOUNTED)来遍历手机的外部存储路径:

File[] files;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    files = getExternalFilesDirs(Environment.MEDIA_MOUNTED);
    for(File file:files){
        Log.e(TAG,file);
    }
}

如果你的手机插了SD卡的话,那么它打印的路径就有两条了,例如我的华为荣耀7插了SD卡,它的结果如下:

/storage/emulated/0/Android/data/packname/files/mounted
/storage/B3E4-1711/Android/data/packname/files/mounted

其中/storage/emulated/0目录就是机身存储的外部存储路径
而/storage/B3E4-1711/就是SD卡的路径,他们统称为外部存储。

1、Environment.getExternalStorageDirectory().getAbsolutePath() = /storage/emulated/0
这个方法是获取外部存储的根路径
2、Environment.getExternalStoragePublicDirectory(“filePath”).getAbsolutePath() = /storage/emulated/0/filePath
这个方法是获取外部存储的自定义路径
3、getExternalFilesDir(“filePath”).getAbsolutePath() = /storage/emulated/0/Android/data/packname/files/filePath
这个方法是获取某个应用在外部存储中的files目录中自定义路径
4、getExternalCacheDir().getAbsolutePath() = /storage/emulated/0/Android/data/packname/cache
这个方法是获取某个应用在外部存储中的cache路径
其中getExternalFilesDir(String type)方法,系统给我们提供了很多常用的type类型,比如图片和下载等等:

public static String DIRECTORY_MUSIC = “Music”;
public static String DIRECTORY_ALARMS = “Alarms”;
public static String DIRECTORY_NOTIFICATIONS = “Notifications”;
public static String DIRECTORY_PICTURES = “Pictures”;
public static String DIRECTORY_MOVIES = “Movies”;
public static String DIRECTORY_DOWNLOADS = “Download”;
public static String DIRECTORY_DCIM = “DCIM”;
public static String DIRECTORY_DOCUMENTS = “Documents”;

路径如下:

Environment.getExternalStorageDirectory()   /storage/emulated/0
getExternalCacheDir()     /storage/emulated/0/Android/data/packageName/cache
getExternalFilesDir("")   /storage/emulated/0/Android/data/packageName/files
getExternalFilesDir("filePath")   /storage/emulated/0/Android/data/packageName/files/filePath
getExternalFilesDir(Environment.DIRECTORY_DCIM)   /storage/emulated/0/Android/data/packageName/files/DCIM

观察上述文件路径,我们发现除了Environment.getDataDirectory().getAbsolutePath()  和Environment.getExternalStorageDirectory()之外,内部存储和外部存储所有的路径都会在packageName之下,即APP专属文件

注意:其中方法3和方法4如果在4.4以前的系统中getExternalFilesDir(“”)和getExternalCacheDir()将返回null,如果是4.4及以上的系统才会返回上面的结果,也即4.4以前的系统没插SD卡的话,就没有外部存储,它的SD卡就等于外部存储;而4.4及以后的系统外部存储包括两部分,getExternalFilesDir(“”)和getExternalCacheDir()获取的是机身存储的外部存储部分,也即4.4及以后的系统你不插SD卡,它也有外部存储,既然getExternalFilesDir(“”)和getExternalCacheDir()获取的是机身存储的外部存储部分,那么怎么获取SD卡的存储路径呢,还是通过上面提到的getExternalFilesDirs(Environment.MEDIA_MOUNTED)方法来获取了。

2.什么是APP专属文件?

所谓专属文件就是它是属于某个具体的应用的,他的文件路径都带有相应的包名,当APP卸载时,它们会随应用一起删除,当我们在设置里面手动清除某个应用数据时(不是清除缓存),它们也会一起被清掉。Android使用这种专属文件的目的就是为了方便文件管理,避免文件随意存储,显得很乱,另一个目的就是为了当应用被卸载时不会留下很多垃圾文件。

3.APP专属文件如何选择?

内部存储与外部存储都有APP专属文件,我们该用哪个呢,很显然应该用外部存储的,因为内部存储本身就比较小,而且已经存储了一些系统的文件,因此内部存储我们尽量不要去使用。但是当手机没有外部存储时,我们还是得使用内部存储,一般程序员会做判断是否有外部存储,没有再使用内部存储,代码如下:

public static String getFilePath(Context context, String dir) {
        String directoryPath;
        if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            //判断外部存储是否可用 
            directoryPath = context.getExternalFilesDir(dir).getAbsolutePath();
        } else {
            //没外部存储就使用内部存储  
            directoryPath = context.getFilesDir() + File.separator + dir;
        }
        File file = new File(directoryPath);
        if (!file.exists()) {
            //判断文件目录是否存在
            file.mkdirs();
        }
        return directoryPath;
    }

4.公共存储目录

该目录下文件不会随APP卸载而消失。

Environment.getExternalStorageDirectory()                   /storage/emulated/0
Environment.getExternalStoragePublicDirectory("")           /storage/emulated/0
Environment.getExternalStoragePublicDirectory("filePath")   /storage/emulated/0/filePath
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) /storage/emulated/0/Pictures

 

参考:https://blog.csdn.net/u010937230/article/details/73303034

    原文作者:长安三日
    原文地址: https://blog.csdn.net/wjr1949/article/details/105945824
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞