storage路径问题

1 概念总述

android开发中,关于存储路径,我们经常听到以下几个概念:内存、内部存储和外部存储,现在我们就来详细说说这三者区别与联系。

内存:英文中记为memory,即RAM

内部存储:英文记为InternalStorage,即内部ROM

外部存储:英文记为ExternalStorage, 即外部ROM和SDCard

由上可知三者在英文中不会产生太大的歧义,但是当我们翻译为中文后,对于三者之间的关系就开始模糊化了。最容易混淆的是外部存储,我们普遍认为机身固有的存储是内部存储,而扩展的T卡是外部存储。早期的android设备内部存储确实是固定的,而外部存储确实是可以像U盘一样移动的。但是在后来的设备中,很多中高端的机器都将自己的机身存储扩展到了8G以上,他们将存储在概念上分成了"内部internal"和"外部external"两部分,但其实都在手机内部。所以不管android手机是否有可移动的sdcard,他们总是有外部存储和内部存储。最关键的是,我们都是通过相同的api来访问可移动的sdcard或者手机自带的存储。

Android 内存

手机的整个存储空间分为内部存储和外部存储两部分,内部存储中又包含RAM和ROM等部分。

内部存储,即InternalStorage,也常说内置存储卡,这是手机内置的存储空间,出厂时就被确定,是手机的一个硬件指标。类比电脑的内存。

外部存储,即ExternalStorage,也常说外置存储卡,手机出厂时并不存在,是由用户自由扩展的存储空间,常见的就是SD卡。类比电脑的外接移动硬盘。
RAM,即常说的运行时内存,是手机运行时存储数据和指令的地方,注意是运行时内存。类比电脑的内存条。

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 目录下对应包名的文件夹及其内容。
该目录下又把存储内容进行了分类:

  • data/data/包名/cache: 存放的 APP 的缓存信息
  • data/data/包名/databases: 存放 APP 的数据库信息
  • data/data/包名/files: 存放 APP 的文件信息
  • data/data/包名/shared_prefs: 存放 APP 内的 SharedPreferences

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 大容量存储以传输文件后,可由用户修改这些文件。

外部存储就是文件系统目录中看到的storage文件夹,也有可能是mnt文件夹,在storage文件夹中有一个sdcard文件夹,这个文件夹中的文件又分为两类,一类是公有目录,还有一类是私有目录,比如DCIM,Download等这些系统为我们创建的文件夹,私有目录就是android这个文件夹,这个文件夹打开后里边有一个data文件夹,打开这个文件夹,里面包含了许多包名组成的文件夹。

1)读取状态

要读取或写入外部存储上的文件,应用必须获取READ_EXTERNAL_STORAGE 或 WRITE_EXTERNAL_STORAGE系统权限。

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();

2)公共目录:

Android 在外部存储上提供了十个公共目录来存储相对应的文件:
通过 API Environment.getExternalStoragePublicDirectory(type) 来访问

  • DIRECTORY_MUSIC:/storage/emulated/0/Music
  • DIRECTORY_PODCASTS:/storage/emulated/0/Podcasts
  • DIRECTORY_RINGTONES:/storage/emulated/0/Ringtones
  • DIRECTORY_ALARMS:/storage/emulated/0/Alarms
  • DIRECTORY_NOTIFICATIONS:/storage/emulated/0/Notifications
  • DIRECTORY_PICTURES:/storage/emulated/0/Pictures
  • DIRECTORY_MOVIES:/storage/emulated/0/Movies
  • DIRECTORY_DOWNLOADS:/storage/emulated/0/Downloads
  • DIRECTORY_DCIM:/storage/emulated/0/Dcim
  • DIRECTORY_DOCUMENTS:/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)其他目录

  1. /cache 目录

    通过 API Environment.getDownloadCacheDirectory() 访问,存储下载文件的缓存路径

  2. /system 目录

    通过 API Environment.getRootDirectory() 访问,该目录下也有一个 app 目录,存放的是系统应用的 apk 文件。

/system/app 和 /data/app 的区别
  • /data/app 里软件权限没全开,/system/app 里的软件获取了所有权限
  • /data/app 可以应用卸载,/system/app 只能 root 后删除
  • /data/app 文件夹大小随便,/system/app 文件夹有大小限制
  • 卸载/system/app 目录下的文件并不会增加系统空间,即可用 ROM 空间
  1. /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

原文地址:https://www.cnblogs.com/jingmengxintang/p/8043271.html

时间: 2024-10-18 13:51:42

storage路径问题的相关文章

HTML5使用local storage存储的数据是如何保存在本地的

HTML5使用local storage存储的数据是如何保存在本地的?(我使用的是chrome浏览器,chrom浏览器是用sqlite来保存本地数据的) HTML5 的local storage 是通过浏览器在本地存储的数据. 基本使用方法如下: <script type="text/javascript"> localStorage.firstName = "Tom"; alert(localStorage.firstName); </scrip

Android 各种路径详细说明

说起Android"内部存储",对于开发者而言可以毫不犹豫地脱口而出,不就是/data/data目录嘛,也不尽然,/data/user/0/又如何解释?那说起"外部存储",例如sd卡目录获取值,更是众说纷纭,是/mnt/sdcard?还是/storage/sdcard0?莫非是/storage/emulated/0? 此疑问起源要追溯到笔者在写上一篇博文,即以DexClassLoader类加载原理编写demo实现类替换修复,其中编码过程中涉及到读写Android内外

用sinopia搭建npm私服

需求(这段话是摘抄参考文档的,因为作者也想这么说): 公司出于自身隐私保护需要,不想把自己的代码开源到包管理区,但是又急需一套完整包管工具,来管理越来越多的组件.模块和项目.对于前端,最熟悉的莫过于npm,bower等:但是bower的市场兼容性明显没有npm强壮,加之commonjs规范的日益成熟.npm应该是前端包管理的不二选择. 公司对于搭建本地私有npm库有如下要求: 私有包托管在内部服务器中 项目中使用了公共仓库上的公共包,也使用了内部服务器上的私有包 希望下载的时候,公共包走公共仓库

VueRouter认识

1. 什么是路由? 路由(vue-router)是负责将进入的浏览器请求映射到特定的 组件 代码中.即决定了由谁(组件)去响应客户端请求.简单说路由就是url地址和对应的资源的映射,通过一个路径的url地址,可以唯一找到一个资源.路由不包含在vue中,是一个插件,需要单独下载. 官方地址:https://router.vuejs.org/zh/ 地址:https://unpkg.com/[email protected]/dist/vue-router.js2.路由的使用 注意:作为vue的插件

laravel框架常用目录路径

app_path() app_path函数返回app目录的绝对路径:$path = app_path(); 你还可以使用app_path函数为相对于app目录的给定文件生成绝对路径:$path = app_path('Http/Controllers/Controller.php'); base_path() base_path函数返回项目根目录的绝对路径:$path = base_path(); 你还可以使用base_path函数为相对于应用目录的给定文件生成绝对路径:$path = base

Android系统文件目录路径说明

系统数据存储路径,如下:其中应用程序包名为:com.spt ContextWrapper类中,包含以下方法: 1. getFilesDir() --> 内部存储 @Override public File getFilesDir() { return mBase.getFilesDir(); } k86m_QC机器上数据存储路径:/data/data/com.spt/files 华为手机上数据存储路径:/data/data/com.spt/files 2. getExternalFilesDir

使用OpenFiler来模拟存储配置RAC中ASM共享盘及多路径(multipath)的测试

第一章 本篇总览 之前发布了一篇<Oracle_lhr_RAC 12cR1安装>,但是其中的存储并没有使用多路径,而是使用了VMware自身提供的存储.所以,年前最后一件事就是把多路径学习一下,本文介绍了OpenFiler.iSCSI和多路径的配置. 本文内容:   第二章 安装OpenFiler OpenFile是在rPath Linux基础上开发的,它能够作为一个独立的Linux操作系统发行.Openfiler是一款非常好的存储管理操作系统,开源免费,通过web界面对存储磁盘的管理,支持现

Sae 上传文件到Storage

首先说一下几个地方: 1.上传使用ss.upload("domin域名","源地址","目标地址,也就是storage的地址");假设要上传到storage某一个详细的文件夹下目标地址写为"upload/"+filename;文件就上传到了upload文件夹下. 2.storage以下全部文件的路径是http://myapp-mybucket.stor.sinaapp.com/path/file.txt  前面是myapp是应

linux 多路径配置

linux 多路径配置                            2017-03-11 20:38:45 标签:linux 多路径 首先介绍一下什么是多路径(multi-path)?先说说多路径功能产生的背景,在多路径功能出现之前,主机上的硬盘是直接挂接到一个总线(PCI)上,路径是一对一的关系,也就是一条路径指向一个硬盘或是存储设备,这样的一对一关系对于操作系统而言,处理相对简单,但是缺少了可靠性.当出现了光纤通道网络(Fibre Channle)也就是通常所说的SAN网络时,或者