说起文件存储,我们可能听说过Android有两个存储区域,分别是内部存储和外部存储,直觉上可能理解成内部存储是手机内置存储,外部存储是指可插拔的SD卡,实际不是这样的理解的,内部和外部并不是以物理来划分,而是以逻辑划分。平时接触较多的Windows系统磁盘划分来理解,Android的内部存储类似于Windows的系统盘,因是Android系统文件和应用安装目录的位置,因此对权限要求严格,除非root,否则用户看不到这个目录,而外部存储是内部存储之外的区域,类似于系统盘之外的其他存储区域。

我们来具体看看区别

  • 内部存储:

    应用程序在内部存储路径空间的路径为data/data/应用对应的包名,该目录只有本程序能访问,其他程序没有权限访问;该目录和应用深度绑定,当应用卸载时,该目录一并删除,不过应用升级更新不会删除该目录;另外内部存储空间有限,文件太多太大影响系统的使用,这就像Windows系统盘文件爆满时影响系统运行,因此尽量别贪图方便往内部存储塞大文件,所谓的贪图方便是操作内部存储不需要开发者申请权限,而操作外部存储多一步申请权限的步骤。

    我们来看一下获取内部存储路径的方法,包括

    • getApplicationInfo().dataDir:获取应用的目录
    • context.getDataDir():获取应用的目录,上个API一样
    • context.getCacheDir():获取应用目录下的Cache文件夹路径
    • context.getFilesDir():获取应用目录下的Files文件夹路径

    然后我们看一下运行返回的结果,程序的包名是com.test.storagedemo,但返回的居然不是data/data/package,而是data/user/0/package?!

    开始我也怀疑是不是搞错了,后来才知道,Android 6.0之后因支持多用户,获取内部存储路径的指令不再返回data/data/package,而是返回/data/user/0/package,其中0是用户编号,每个用户拥有自己的私人数据空间,用户0只能访问/data/user/0/下的数据,用户1只能访问/data/user/1/下的数据。data/data/package变成了快捷方式,返回当前用户的路径,也就是说,如果是用户0在用,则data/data/package链接到/data/user/0/package

    getApplicationInfo().dataDir:/data/user/0/com.test.storagedemo
    context.getCacheDir():/data/user/0/com.test.storagedemo/cache
    context.getFilesDir():/data/user/0/com.test.storagedemo/files
    context.getDataDir():/data/user/0/com.test.storagedemo
    
  • 外部存储:

    内部存储之外统称为外部存储,外部存储分为公共目录和私有目录,公共目录包括Download,DCIM,Music等,私有目录是名为Android的文件夹,该文件夹的子目录是data,而data目录下则是包名文件夹,这个目录和内部存储程序文件目录长起来差不多,其实就是程序在外部存储的私有目录,和内部存储不同的是,这里虽然是私有目录,但其他程序只要知道这个目录,都可以访问该目录,是程序在外部存储弄的一个程序自留地,目的也是为了方便开发和管理文件,方便开发是指从Android 4.4 开始,操作外部存储的私有目录不需要申请READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE权限,而方便管理是指私有目录会随着应用的卸载一并删除,这样不会因为卸载留下垃圾文件,避免用户反感。

    不过操作公共目录仍需要申请READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE,申请的方法是在AndroidManifest.xml添加权限申请

     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

    操作外部存储也有对应的API,分别是

  • Environment.getExternalStorageState:判断外置存储是否挂载着,因为外部存储可能是可插拔的SD卡,在使用之前先检查是否挂载是一个增加程序健壮性的方法;

  • Environment.getExternalStorageDirectory:获取外部存储目录

  • Environment.getExternalStoragePublicDirector(Environment.DIRECTORY_DCIM:获取外部存储DCIM目录,如果没有DCIM则会创建;

  • context.getExternalCacheDir():获取外部存储私有目录下的Cache目录;

  • context.getExternalFilesDir(Environment.DIRECTORY_PICTURES):获取外部存储私有目录下Pictures目录;

运行一下这些API,得到如下结果

Environment.getExternalStorageState:mounted
Environment.getExternalStorageDirectory:/storage/emulated/0
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM:/storage/emulated/0/DCIM
context.getExternalCacheDir():/storage/emulated/0/Android/data/com.test.storagedemo/cache
context.getExternalFilesDir(Environment.DIRECTORY_PICTURES):/storage/emulated/0/Android/data/com.test.storagedemo/files/Pictures

结合运行结果,可以反过来看一下API,不知道大家有没有注意到,公共目录是用EnvironmentAPI获取,私有目录是用Context获取,Context是应用的上下文,可直接获取到包名,因此包括内部存储,带包名的使用Context获取,没有包名则使用Environment获取。

因我的环境是在虚拟机上运行,路径中是emulated,在手机上运行可能返回结果不一样。

再将以上内容总结一下:

  • Android存储可分为内部存储和外部存储,程序访问自己内部存储目录不需要申请权限,其他程序无法访问本程序的内部存储,内部存储空间有限,大文件尽量别往内部存储保存,程序内部存储随着程序的卸载而删除;
  • 外部存储分为公共目录和私有目录,访问外部存储需要申请权限,不管公共目录还是私有目录,任何程序都可以访问,程序外部存储的私有目录同样会随着应用的卸载一并删除;
  • 访问带包名的目录使用ContextAPI,访问不带包名的使用EnvironmentAPI;
  • Android 6.0后,因支持多用户,因此操作内部存储不是返回data/data/package,而是返回data/user/0/package,前者变成一个快捷方式,链接到后者。

说了半天内部存储和外部存储,好像还没提到该怎么存储文件,其实理解内部存储和外部存储,可更好的理解存储API的调用,文件存储API调用是相对简单的,如下是一个在内部存储存下一个文件和从内部存储取出一个文件的代码,存储使用的是openFileOutput,内部存储路径是相对固定的,函数不需要指定路径,只需要给一个文件名即可。取数据使用openFileInput,同样需要指定文件名即可。从这两个函数可以实际体验到为什么使用内部存储方便,一个是不用申请权限,二是连路径都不用指定。

public void save(){String data = "Data for Save";FileOutputStream out = null;ButteredWriter writer = null;try{//第一个参数 文件名;第二个参数 文件操作模式; 返回 FileOutputStream对象out = openFileOutput("data",Context.MODE_PRIVATE); //实例化一个ButterWriterwriter = new ButteredWriter(new OutputSreamWriter(out));writer.write(data);}catch(IOException e){e.printStackTrace();}finally{try{if(writer!=null){writer.close();}}catch(IOException e){e.printStackTrace();}
}

public String load() {FileInputStream in = null;BufferedReader reader = null;StringBuilder content = new StringBuilder();try {//传入文件名参数,返回FileInputStream对象in = openFileInput("data");reader = new BufferedReader(new InputStreamReader(in));String line = "";while ((line = reader.readLine()) != null) {content.append(line);}} catch (IOException e) {e.printStackTrace();} finally {if (reader != null) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}return content.toString();
}

函数写好之后,调用save()保存,再调用load()加载即可打印出信息。使用Android Studio的Device Explorer找到data/data/com.test.storagedemo/files目录,可看到刚才存储的名为data的文件。

Android持久化存储(1)文件存储相关推荐

  1. Android基础知识(二十一):Android五大存储之文件存储、Content Provider存储和网络存储

    Android基础知识(二十一):Android五大存储之文件存储.Content Provider存储和网络存储 一.Android存储--持久化技术 数据持久化是指将那些内存中的瞬时数据保存到存储 ...

  2. android文件存储数组,Android面试简录——文件存储

    * SharedPreferences 请描述Android SDK支持哪些文件存储技术? 1.SharedPreferences保存key-value类型的数据 2.流文件存储(openFileOu ...

  3. Android 保存QQ密码(数据存储:文件存储、SharedPreferences)

    源码[工程文件]:https://gitee.com/lwx001/saveQQ MainActivity.java: package cn.lwx.saveqq;import android.os. ...

  4. Android(数据存储:文件存储、SharedPreferences)验证QQ密码

    前情提要1 :静态页面-简易QQ登录页面(纯activity_main.xml页面) [https://blog.csdn.net/weixin_44949135/article/details/10 ...

  5. 对象存储与块存储、文件存储等对比

    看到 一篇文档, 讲 对象存储, 好奇,搜索文章,摘抄,学习记录 ! 背景: 传统存储在面对海量非结构化数据时,在存储.分享与容灾上面临很大的挑战,主要表现在以下几个方面:传统存储并非为非结构化内容设 ...

  6. 块存储、文件存储、对象存储这三者和分布式文件存储系统的本质区别

    块存储和文件存储是我们比较熟悉的两种主流的存储类型,而对象存储(Object-based Storage)是一种新的网络存储架构,基于对象存储技术的设备就是对象存储设备(Object-based St ...

  7. 如何修改xd.properties文件中对象存储文件信息_对块存储、文件存储、对象存储的认识总结...

    因工作原因接触了对象存储,从而了解到相关的块存储和文件存储.搜罗了网上各种信息,结合自己的理解,整理如下.欢迎阅读,批评指正. 开头引用下几篇关于"块存储.文件存储.对象存储"的文 ...

  8. 天翼云从业认证(1.2)存储的概念、体系结构、块存储、对象存储、文件存储以及 RAID 磁盘管理技术

    (1)块存储.对象存储.文件存储 存储方式 技术实现 优势 劣势 代表作 块存储 裸盘上划分逻辑卷,逻辑卷格式化成任意文件系统 支持多种文件系统,传输速度快,提供硬件容错机制 无法实现网络共享 FC- ...

  9. mysql存储文件用什么类型_块存储、文件存储、对象存储的区别是什么?

    块存储: 需要实现Linux的Block Device的接口或者QEMU提供的Block Driver接口.提供随机读写,可以像使用物理硬盘一样格式化并建立文件系统来使用块存储,块存储可用于绝大部分通 ...

  10. 块存储、文件存储、对象存储意义及差异

    关于块存储.文件存储.对象存储方面的知识在知乎上看到了个很好的解答:https://www.zhihu.com/question/21536660 通俗易懂,查了些资料做了详细的补充. 块存储 典型设 ...

最新文章

  1. java mysql failover_MySQL MMM 双主在Failover时挂起
  2. scala tail recursive优化,复用函数栈
  3. 我的世界java8_《我的世界》java8 64服务器mod
  4. 数据库菜鸟不可不看 简单SQL语句小结
  5. java 广播地址,根据ip地址跟子网掩码获取广播地址的java实现
  6. MVVM模式的3种command总结[2]--RelayCommand
  7. SpringSecurity分布式整合之认证服务配置文件编写和测试
  8. java(i++和++i的理解)
  9. 形成20位存储单元的物理地址
  10. 大数据分块_谷歌卫星影像金字塔分块下载原理说明
  11. 网易云音乐的品牌竞争力研究
  12. 打印机怎么连接电脑使用
  13. 【上网】微信能上网,谷歌浏览器上不了网,怎么解决?
  14. 设置hyper-v虚拟机的enhanced session mode
  15. superset汉化
  16. 常见的服务器类型有哪些?
  17. 谷歌浏览器调试前端功能时的三种刷新方式
  18. unity使用tiled文件,将数据用unity打开,可以无限tiled地图
  19. java线段绕原点旋转的方法,将点绕坐标原点顺时针旋转得到点的坐标为___________。-九年级数学-魔方格...
  20. 海思Hi3559(十)——生成wk数据文件

热门文章

  1. boost::mpi模块实现scan集合的测试
  2. boost::mp11::mp_less相关用法的测试程序
  3. boost::mp11::mp_eval_if_not_q相关用法的测试程序
  4. hana::detail::variadic::reverse_apply用法的测试程序
  5. boost::describe模块实现连载功能的测试程序
  6. ITK:二维高斯混合模型期望最大化
  7. VTK:相互作用之Assembly
  8. OpenCV视差图后过滤
  9. OpenGL基于PBR的irradiance辐照度的实例
  10. C++数据结构之链式结构