1 概念总述linux
android开发中,关于存储路径,咱们常常听到如下几个概念:内存、内部存储和外部存储,如今咱们就来详细说说这三者区别与联系。android
内存:英文中记为memory,即RAM数据库
内部存储:英文记为InternalStorage,即内部ROMapi
外部存储:英文记为ExternalStorage, 即外部ROM和SDCard缓存
由上可知三者在英文中不会产生太大的歧义,可是当咱们翻译为中文后,对于三者之间的关系就开始模糊化了。最容易混淆的是外部存储,咱们广泛认为机身固有的存储是内部存储,而扩展的T卡是外部存储。早期的android设备内部存储确实是固定的,而外部存储确实是能够像U盘同样移动的。可是在后来的设备中,不少中高端的机器都将本身的机身存储扩展到了8G以上,他们将存储在概念上分红了"内部internal"和"外部external"两部分,但其实都在手机内部。因此无论android手机是否有可移动的sdcard,他们老是有外部存储和内部存储。最关键的是,咱们都是经过相同的api来访问可移动的sdcard或者手机自带的存储。微信
Android 内存app
手机的整个存储空间分为内部存储和外部存储两部分,内部存储中又包含RAM和ROM等部分。函数
内部存储,即InternalStorage,也常说内置存储卡,这是手机内置的存储空间,出厂时就被肯定,是手机的一个硬件指标。类比电脑的内存。测试
外部存储,即ExternalStorage,也常说外置存储卡,手机出厂时并不存在,是由用户自由扩展的存储空间,常见的就是SD卡。类比电脑的外接移动硬盘。
RAM,即常说的运行时内存,是手机运行时存储数据和指令的地方,注意是运行时内存。类比电脑的内存条。spa
ROM,用来存放一些系统文件,应用配置和其余数据的地方,是内部存储中主要存储区域。类比于Windows电脑的C盘。
在 Android Studio 使用 DDMS 的 File Exploer 窗口中查看文件系统,下图就是一个 Android 文件系统目录。
Android 文件系统目录
这里有三个文件夹须要注意,data、mnt和storage,data是指内部存储,mnt和storage指外部存储。下面将详细介绍内部存储和外部存储。
2 内部存储
内部存储位于系统中很特殊的一个位置,若是你想将文件存储于内部存储中,那么文件默认只能被你的应用访问到,且一个应用建立的全部文件都在和应用包名相同的目录下。当一个应用卸载后,内部存储中的这些文件也被删除。内部存储空间十分有限,它是系统自己和系统应用程序主要的数据存储所在地,一旦内部存储空间耗尽,手机就没法使用了。Shared Preferences和SQLite数据库都是存储在内部存储空间上的。内部存储通常用Context来获取和操做。内部存储有两个重要目录:
1)app文件夹:没有root的手机不能打开该文件夹。app文件夹里存放着系统中安装的第三方应用的apk文件,当咱们调试一个app的时候,能够看到控制台输出的内容,有一项是uploading...,就是上传咱们的apk到这个文件夹,上传成功后才开始安装。
2)data文件夹:
该文件夹存放存储包私有数据,对于设备中每个安装的 App,系统都会在内部存储空间的 data/data 目录下以应用包名为名字自动建立与之对应的文件夹。
用户卸载 App 时,系统自动删除 data/data 目录下对应包名的文件夹及其内容。
该目录下又把存储内容进行了分类:
3)路径获取API
/data Environment.getDataDirectory();
/data/data/包名/files context.getFilesDir();
//对于 Files 目录下的文件,一般不会经过 File 类的方式直接进行读写,而是利用一些封装过的类或函数进行操做: public FileInputStream openFileInput(String name) public FileOutputStream openFileOutput(String name, int mode)
//还能够直接删除或查询该目录下的文件: context.deleteFile(name) context.fileList()
/data/data/包名/cache context.getCacheDir();
/data/data/包名/shared_prefs context.getSharedPreferences(name,mode)//返回的是 SharedPreferences 对象 context.deleteSharedPreferences(name)
/data/data/包名/databases context.getDataDir() context.getDatabasePath(name) context.deleteDatabase(name)
/data/data/包名/app_name context.getDir(name,mode) //经测试该方法会在 /data/data/包名/ 目录下生成一个以 app_ 开头的目录
3 外部存储
每一个兼容 Android 的设备都支持可用于保存文件的共享“外部存储”。 该存储多是可移除的存储介质(例如 SD 卡)或内部(不可移除)存储。 保存到外部存储的文件是全局可读取文件,并且,在计算机上启用 USB 大容量存储以传输文件后,可由用户修改这些文件。
Environment.getExternalStorageState()
返回值为如下几种:
MEDIA_MOUNTED:sd卡正常挂载
MEDIA_REMOVED:无介质
MEDIA_UNMOUNTED:有介质,未挂载,在系统中删除
MEDIA_BAD_REMOVAL:介质在挂在前被移除,直接取出sd卡。
MEDIA_CHECKING:正在磁盘检查,刚装上sd卡时
MEDIA_SHARED:sd卡存在但没有挂载,而且经过USB大容量存储共享,操做打开USB存储
MEDIA_MOUNTED_READ_ONLY:sd卡存在而且已挂载,可是挂载方式为只读
MEDIA_NOFS:介质存在可是为空白,或用在不支持的文件系统
MEDIA_UNMOUNTABLE:存在sd卡可是不能挂载,例如发生介质损坏
挂载:这是linux系统的术语,就是加载的意思,把sd卡划入系统相连,让系统能认到并读取sd卡的内容。
当sd卡状态为MEDIA_MOUNTED时,/mnt/sdcard目录才是可读可写,而且能够建立目录及文件。其余状况一概不可读可写。
读取sd卡通常会这么写。
String state; String path; state = Environment.getExternalStorageState(); if(state.equals(Environment.MEDIA_MOUNTED)){ path = Environment.getExternalStorageDirectory().getAbsolutePath(); }
读写sd卡不要忘了权限问题,需加入如下两个权限
* 1 在AndroidManifest文件中加入sdcard操做权限 <!--在SDCard中建立与删除文件权限 --> <uses-permissioandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!--往SDCard写入数据权限 --> <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/> * 2 确认sdcard的存在 android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED) * 3 获取扩展存储设备的文件目录 android.os.Environment.getExternalStorageDirectory();
Android 在外部存储上提供了十个公共目录来存储相对应的文件:
经过 API Environment.getExternalStoragePublicDirectory(type)
来访问
/storage/emulated/0/Music
/storage/emulated/0/Podcasts
/storage/emulated/0/Ringtones
/storage/emulated/0/Alarms
/storage/emulated/0/Notifications
/storage/emulated/0/Pictures
/storage/emulated/0/Movies
/storage/emulated/0/Downloads
/storage/emulated/0/Dcim
/storage/emulated/0/Documents
3)私有目录
Android2.2 引入了基于扩展存储器的应用缓存目录,该目录指向大容量的扩展存储器。与应用的内存私有目录同样,缓存目录会随着应用的卸载一并删除。
和内部存储同样,会在 SD 卡的 Android/data 目录下生成对应包名的文件夹
/storage/emulated/0/Android/data/应用包名/files context.getExternalFilesDir(type)
/storage/emulated/0/Android/data/应用包名/cache context.getExternalCacheDir()
在 Android 目录下除了 data 目录还有一个 obb 目录 /storage/emulated/0/Android/obb/应用包名 context.getObbDir()
4)其余目录
Environment.getDownloadCacheDirectory()
访问,存储下载文件的缓存路径Environment.getRootDirectory()
访问,该目录下也有一个 app 目录,存放的是系统应用的 apk 文件。/mnt 目录
这个目录专门用来看成挂载点挂在外部设备的,如 SD 卡,sdcard
将会被系统视做一个文件夹,这个文件夹将会被系统嵌入到收集系统的 mnt 目录中,因此在 /mnt 目录下也会看到一个 sdcard 的快捷方式:
4 总结
A: getCacheDir(): 获取/data/data//cache目录
getFileDir(): 获取/data/data/files目录
这两个目录中的内容必须是root的手机在文件操做系统中才能看到。固然若是在应用程序中清空数据或者卸载应用,那么这两个目录下的文件也将会被清空的。
B: getExternalFilesDir(): 获取SDCard/Android/data/你的应用的包名/files/目录(通常存放一些长时间保存的数据)
getExternalCacheDir(): 获取SDCard/Android/data/你的应用包名/cache/目录(通常存放临时缓存的数据)
这两个是放在外置存储卡的,这个目录下的内容,可使用文件浏览系统查看到,可是若是清空数据或者卸载应用,这两个目录下的文件也将被清空。
当应用被用户卸载后,SDCard/Android/data/你的应用包名/这个目录下的全部文件都会被删除,不会留下垃圾信息。A、B两种方式的缓存都会在卸载app的时候被系统清理到,而开发者本身在sd卡上创建的缓存文件夹,是不会随着app的卸载而被清除掉的。
getCacheDir:/data/data/com.example.sinatext/cache getFilesDir:/data/data/com.example.sinatext/files getExternalCacheDir:/storage/sdcard0/Android/data/com.example.sinatext/cache getExternalFilesDir:/storage/sdcard0/Android/data/com.example.sinatext/files/text getDatabasePath:/data/data/com.example.sinatext/databases/text getDir:/data/data/com.example.sinatext/app_modeDir getPackageResourcePath:/data/app/com.example.sinatext-2.apk Environment.getDataDirectory():/data Environment.getExternalStorageState():mounted Environment.getDownloadCacheDirectory():/cache Environment.getExternalStorageDirectory():/storage/sdcard0 Environment.getRootDirectory():/system
按照路径的特征,咱们又能够将文件存储的路径分为两大类,一类是路径中含有包名的,一类是路径中不含有包名的,含有包名的路径,由于和某个App有关,因此对这些文件夹的访问都是调用Context里边的方法,而不含有包名的路径,和某一个App无关,咱们能够经过Environment中的方法来访问。
清除数据:相似于恢复出厂设置,删除了全部用户保存的数据。则是指一些固定的用户信息,好比登陆信息、进度保存信息等,清理以后,再次运行对应的App,好比微信,则须要从新输入登陆信息,而若是是游戏,特别是单机游戏,则就像新游戏同样,以前的进度信息都会被清除而没法继续。即将外部私有数据包(/storage/emulated/0/Android/data/包名)清除,将内部数据下的全部内容(/data/data/包名/XXX)清除;
清除缓存:只是删除了应用软件的缓存资源。手机App应用在运行过程当中会产生一些临时数据,好比加载过的页面、填写过的数据等,这些数据的存在有利于对应App无需屡次加载而运行加快,这些数据称之为“缓存数据“。清理缓存表示将这些临时数据清除,清除后,对应App再次运行须要从新生成,可能会变慢,可是总体手机运行内存因其释放而增长,反而可能加快。即将外部私有数据下的cache包(/storage/emulated/0/Android/data/包名/cache)清除,将内部数据下的cache包下的内容(/data/data/包名/cache/XXX)清除 。
参考博文http://blog.csdn.net/summerinnphuket/article/details/50790365https://www.jianshu.com/p/80e10b3dbba5