浅谈Android的文件存储

由于项目须要,最近学了不少数据本地持久化的知识。有不少情景咱们都须要遇到文件存储:从保存用户的登陆状态到记录浏览信息,从保存图片到下载大型文件。因此有必要了解下Android的文件存储系统,从而轻松地去管理咱们应用日常产生的数据。java

内部存储

这是按存储的位置来分的。应用对内部存储操做不须要任何的权限,这就意味着不须要在AndroidManifest.xml里声明权限,也不须要在Android6.0上进行权限适配。其实作过权限适配同窗都清楚,只有外部存储的权限:Manifest.permission.READ_EXTERNAL_STORAGEManifest.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安全

其余两个是缓存文件夹,当内部存储空间不足时,系统会自动优先删除 cache和 code_cache文件夹里的内容。code_cache文件夹在运行时存放应用产生的编译或者优化的代码,感受日常用不到。

其余工做目录

上面仅仅是一个全新应用预先建立的内部存储目录。其余相关的子目录以下(使用时建立):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_STORAGEManifest.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

一些总结

  • 通常状况下有包名的路径咱们都是调用Context中的方法来得到,没有包名的路径,咱们直接调用Environment中的方法得到。
  • 使用外部存储前要检测权限和检测状态是否可用(一般对于sd卡来讲),若是不能用就只能用内部存储了:
state = Environment.getExternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED)){
    //todo
}
复制代码
  • 关于设置->应用->应用详情里面的”清除数据“与”清除缓存“选项,前者会删除全部的内部存储和外部存储的应用专属文件目录的文件夹;后者只会清楚内部存储和外部存储专属文件目录下的缓存文件夹。
相关文章
相关标签/搜索