由于项目须要,最近学了不少数据本地持久化的知识。有不少情景咱们都须要遇到文件存储:从保存用户的登陆状态到记录浏览信息,从保存图片到下载大型文件。因此有必要了解下Android的文件存储系统,从而轻松地去管理咱们应用日常产生的数据。java
这是按存储的位置来分的。应用对内部存储操做不须要任何的权限,这就意味着不须要在AndroidManifest.xml
里声明权限,也不须要在Android6.0上进行权限适配。其实作过权限适配同窗都清楚,只有外部存储的权限:Manifest.permission.READ_EXTERNAL_STORAGE
和Manifest.permission.WRITE_EXTERNAL_STORAGE
。我的理解:权限是为了系统保证应用安全和用户安全而设的,既然系统对内部存储有着最高的管理权限,应用只能在系统分配的空间存储文件,就不必有这个内部存储权限
了。android
咱们App在内部存储都有本身的专有目录: /data/data/PackageName
。存放了 WebView 缓存页面信息,SharedPreferences 和 数据库数据等。不过没root的是看不到的.固然咱们能够经过Android Studio主界面右下处的Device File Exploer
来查看:web
建立一个新应用,包名:com.renny.storage
,系统在内部存储默认建立了三个空文件夹,经过Context来获取下:数据库
File getFilesDir()
:返回内部存储的Files文件夹File getCacheDir()
:返回内部存储的cache文件夹File getCodeCacheDir()
:返回内部存储的code_cache文件夹,要求Android5.0+File getDataDir()
: 返回内部存储的根文件夹,要求Android7.0+一般咱们将文件存放在的Files文件夹,经过fileList()
能够获取该文件夹下的所有文件的文件名。openFileInput()
和 openFileOutput()
方法也是在该目录下操做文件。这些方法都是Context里的,在activity中能够直接调用。举个例子:缓存
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try{
FileOutputStream outputStream = openFileOutput("hello.text", Context.MODE_PRIVATE);
outputStream.write( "Hello world!".getBytes());
outputStream.close();
} catch(IOException e) {
e.printStackTrace();
}
String[] files = fileList();
for (String file : files) {
Log.d("file--",file);
}
}
复制代码
这样就会在Files文件夹下面生成一个hello.text
文件了,打印出的信息就是 hello.text
。安全
上面仅仅是一个全新应用预先建立的内部存储目录。其余相关的子目录以下(使用时建立):cookie
/data/data/PackageName/shared_prefs/
:
用来存储 SharedPreference,相关函数为:getSharedPreferences(String fileName, int mode);
app
/data/data/PackageName/databases/
ide
用来存储数据库文件,相关函数: getDatabasePath()
;函数
/data/data/PackageName/app_webview
/data/data/PackageName/xxxwebviewcachexxx
存储应用内置 webview 所产生的 cache 和 cookies 等,该目录因为 android 版本不一样名字和位置也可能不一样;
/data/data/PackageName/lib
用来存储该应用的 .so 静态库文件;
内部存储空间较小,由于只对应用自己可见,适合保存一些私密信息,好比登陆信息,须要加密的数据等等,当一个应用卸载以后,内部存储中的这些文件也会被删除。另外内部存储的文件读取速度通常也是高于外部存储的。
外部存储空间就很是大了,你们买的手机32Gb,64Gb容量,还有还有XXGb的SD卡,都是外部存储。外部存储能够直接在手机的文件管理应用中浏览。外部存储中的文件是能够被用户或者其余应用程序修改的(系统无论了),因此读写也须要Manifest.permission.READ_EXTERNAL_STORAGE
和Manifest.permission.WRITE_EXTERNAL_STORAGE
权限,来让用户本身管理。 有了权限,外部存储的全部目录咱们都能访问到。 好比根目录: Environment.getExternalStorageDirectory()
下面咱们按照存储内容的用途来介绍:
Environment.getExternalStoragePublicDirectory(int type)
根据type会返回对应的文件目录。这些文件目录就是用来存放全部App均可能会用到的一些文件。type有不少种,好比: Environment.DIRECTORY_DCIM
,获得的就是外部存储根文件夹下的DCIM文件夹,也就是手机存储照片的地方。经常使用的还有:
Environment.DIRECTORY_DOWNLOADS
Download文件夹Environment.DIRECTORY_MUSIC
Music文件夹Environment.DIRECTORY_MOVIES
Movies文件夹等等等等。通常把须要和其余应用共享的文件均可以放这里(不过状况好像不是不少)。
虽然在外部存储管不了应用在哪存取文件,但也不能任由应用胡乱在任何位置存文件,并且这些文件在应用卸载了之后也要删除吧,否则到后来外部存储全是卸载后应用留下的垃圾文件。因此Android有个目录用来专门给应用存文件(固然想不想在那存,系统管不了)。目录结构相似于内部存储:
/storage/emulated/0/Android/data/PackageName/
方法也和内部存储很相似:
Context.getExternalFilesDir(String type)
:Android/data/PackageName/files文件夹
Context.getExternalCacheDir()
:Android/data/PackageName/cache文件夹 上面的type和Environment.getExternalStoragePublicDirectory(int type)
用法是相似的,有一点不一样:
能够为空:getContext().getExternalFilesDir(null)
:此时就是files根文件夹 Android/data/packageName/files
;
也能够传一个值: getContext().getExternalFilesDir("apple")
:此时就是files文件夹下的子文件夹:Android/data/packageName/files/apple
。
state = Environment.getExternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED)){
//todo
}
复制代码