当前位置: 首页 > news >正文

【Android】内外部存储的读写

在这里插入图片描述
三三要成为安卓糕手

一:安卓中文件存储位置

  • 应用内部存储空间目录:这些目录既包括用于存储持久性文件的专属位置,也包括用于存储缓存数据的其他位置。系统会阻止其他应用访问这些位置,并且在 Android 10(API 级别 29)及更高版本中,系统会对这些位置进行加密。这些特征使得这些位置非常适合存储只有应用本身才能访问的敏感数据。
  • 应用专属外部存储:这些目录既包括用于存储持久性文件的专属位置,也包括用于存储缓存数据的其他位置。其他应用可以在具有适当权限的情况下访问这些目录,更多的还是自己使用。当应用被卸载时,存储在这里的文件会被删除。
  • 公共存储空间:如果明确打算创建其他应用能够访问的文件,可以将文件存储在外部存储空间的共享存储空间部分所有应用均可访问,适合存储对所有应用可见的数据,如图片、音乐、视频等

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

二:应用内部私有存储数据的写入

internal 内部的

external 外部的

1:客户端布局

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".file.PrivateFileActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="应用内部私有存储相关操作"android:textSize="30sp" /><Buttonandroid:id="@+id/btn_internal_save"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="保存文件" /><Buttonandroid:id="@+id/btn_internal_read"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="读取文件" /><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="30dp"android:text="应用外部私有存储相关操作"android:textSize="30sp" /><Buttonandroid:id="@+id/btn_external_save"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="保存文件" /><Buttonandroid:id="@+id/btn_external_read"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="读取文件" /><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="20dp"android:text="=============我是分割线==========="android:textSize="20sp" /><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="我想把这段内容保存到文件当中"android:textSize="20sp" /><EditTextandroid:id="@+id/et_info"android:layout_width="match_parent"android:layout_height="wrap_content" /><TextViewandroid:id="@+id/tv_info"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:text="读取到了如下信息:\n" /></LinearLayout>

2:数据写入文件代码

        findViewById(R.id.btn_internal_save).setOnClickListener(view -> {new Thread() {@Overridepublic void run() {super.run();File file = new File(getFilesDir(), "content.txt");Log.i(TAG, "run: absolutePath: " + file.getAbsolutePath());try (FileOutputStream fos = new FileOutputStream(file);//缓冲输出流BufferedOutputStream bos = new BufferedOutputStream(fos)) {//获取框中的数据String content = etInfo.getText().toString().trim();byte[] bytes = content.getBytes();bos.write(bytes, 0, bytes.length);} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}}.start();});
  • getFilesDir():返回内部存储位置的目录 ; "context.txt"给即将创建的文件取得名字
  • 资源自动关闭:传统方式在 try 块中创建流,需要在 finally 块中显式调用 close() 手动释放资源;这里直接放到try()括号中,操作完毕会自动关闭资源;(流操作实现了 AutoCloseable 接口)
  • 缓冲输出流:遇到大文件,不会很吃力;攒一波数据一次性写入,减少读写次数,提高效率;内部本身自带一个字节数组,这里我们自己申请了一个;资源自动close() 前内部会先调用 flush(),保证缓冲区中剩余的所有数据(可能缓冲区没攒满一波也能)写入到底层输出流
  • bos.write():传入有数据的数组,从offset到末尾所有的数据写入到文件中
  • 读文件是一个耗时的操作,放在子线程中

3:如何理解输入和输出流

理清楚程序(也就是代码)和文件之间的流向就能区分开

  • “从文件里读取内容,放到程序里”,数据流向是:文件 → 程序 那就是输入流InputStream 相关类)
  • “把代码中的数据(比如说输入框EditText中的内容),存储到文件里” 数据的流向:程序 → 文件 那就是输出流OutputStream 相关类)

4:如何理解字节和字符

程序这边就是字符,存储一方就是字节;所以输出流操作时,往往先要把字符数据转换为字节格式,在写入保存到文件中

上面代码中的流程:字符串(字符)→ 字节数组 → 字节流写入文件

  • 程序里操作的是输入框中的字符内容(String 类型)。
  • 当要写入文件时,通过 content.getBytes() 把字符转换为字节,然后用字节流(FileOutputStreamBufferedOutputStream)将字节写入文件存储。

5:如何理解缓冲流

BufferedOutputStream缓冲流: 是先将数据暂存在内存缓冲区中,当缓冲区满了自动或手动调用 flush()/close() 时,才会将数据真正写入底层的 FileOutputStream(即磁盘文件)

6:效果

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

三:应用内部私有存储数据的读取

findViewById(R.id.btn_internal_read).setOnClickListener(view -> {new Thread(new Runnable() {@Overridepublic void run() {//拿到这个文件对象File file = new File(getFilesDir(), "content.txt");//FileInputStream本身读取的是字节,转化成读字符try (FileInputStream fis = new FileInputStream(file);InputStreamReader isr = new InputStreamReader(fis);//字节流转化为字符流BufferedReader br = new BufferedReader(isr)//缓冲读取) {StringBuffer buffer = new StringBuffer();String line;while((line = br.readLine()) != null){buffer.append(line);}String result = buffer.toString().trim();tvInfo.setText(tvInfo.getText() + result);} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}}).start();});

1:字节转换字符

通过 InputStreamReader 把字节流转为字符流,再用 BufferedReader 包装,readLine读取

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2:效果

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

四:应用外部私有存储数据的写入

        findViewById(R.id.btn_external_save).setOnClickListener(view -> {String state = Environment.getExternalStorageState();Log.i(TAG, "onCreate: 外部存储状态"+" "+ state);if (Environment.MEDIA_MOUNTED.equals(state)){//既可读又可写File file = new File(getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "content.txt");String path = file.getAbsolutePath();Log.i(TAG, "onCreate: 文件的路径是" + path);//把字符流转化为字节流,从程序写到硬盘中try (FileOutputStream fos = new FileOutputStream(file);BufferedOutputStream bos = new BufferedOutputStream(fos)){String text = etInfo.getText().toString().trim();byte[] bytes = text.getBytes();bos.write(bytes,0,bytes.length);} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {//只读}else{//外部存储不可用}});

1:获取外部文件路径

  • getExternalFilesDir():返回外部私有目录
  • Environment.DIRECTORY_DOCUMENTS:DOCUMENTS指的就是下图中的文件夹,可能还会有Picture文件夹对应的就是PICTURE;这是内部封装好的常量值,当然也可以直接传入字符串

2:外部文件读写权限

  • Environment.getExternalStorageState(); 获取外部存储状态
  • Environment.MEDIA_MOUNTED 既可读又可写
  • Environment.MEDIA_MOUNTED_READ_ONLY 只能读取
  • Environment.MEDIA_UNMOUNTED 未挂载

3:挂载的概念

media媒体 mounted已挂载

简单说,“挂载” 就是给存储设备(比如 U 盘、SD 卡)在系统里 “办个接入手续”,让系统能找到它、用它。

比如插 U 盘到电脑,系统弹出 U 盘图标,就是完成了挂载;安卓手机识别到 SD 卡能存照片,也是 SD 卡挂载成功了。

4:效果

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

五:应用外部私有存储数据的读取

        findViewById(R.id.btn_external_read).setOnClickListener(view -> {String state = Environment.getExternalStorageState();if (Environment.MEDIA_MOUNTED.equals(state)){File file = new File(getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "content.txt");try(FileInputStream fis = new FileInputStream(file);InputStreamReader isr = new InputStreamReader(fis);BufferedReader reader = new BufferedReader(isr)){StringBuffer buffer = new StringBuffer();String line;while((line = reader.readLine()) != null){buffer.append(line);}String result = buffer.toString();Log.i(TAG, "onCreate: result " + result);tvInfo.setText(tvInfo.getText() + result);} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}});

4.0~6.0低版本的安卓,都可以用上述方法对内部存储文件进行处理;高版本的安卓,对处理文件的权限要求越发的严格,就要使用一些更新的方式去访问外部存储权限,


文章转载自:

http://xLWRBUk0.nmngq.cn
http://BSHi5jlF.nmngq.cn
http://7jvNjACQ.nmngq.cn
http://YNrwA4QN.nmngq.cn
http://6pwOZfTB.nmngq.cn
http://1YfEMH1C.nmngq.cn
http://nqRHgvr3.nmngq.cn
http://9XTaLeoy.nmngq.cn
http://YZFVHKwF.nmngq.cn
http://VbS6jBhJ.nmngq.cn
http://9JuWb0Ez.nmngq.cn
http://dLgatvxX.nmngq.cn
http://lRhc83Te.nmngq.cn
http://PNToSkIO.nmngq.cn
http://816ClvHk.nmngq.cn
http://HbYnrljB.nmngq.cn
http://fuXbCwRe.nmngq.cn
http://SnYEBU3W.nmngq.cn
http://DGuqEnzV.nmngq.cn
http://eLSuZ45L.nmngq.cn
http://grNaII0o.nmngq.cn
http://anydOboI.nmngq.cn
http://F9bIFEHW.nmngq.cn
http://eKqOKVUF.nmngq.cn
http://jrBweY3W.nmngq.cn
http://K4iUBOCt.nmngq.cn
http://d1wTxmaF.nmngq.cn
http://63YXO0DV.nmngq.cn
http://YjGmfyih.nmngq.cn
http://uWE5LpTn.nmngq.cn
http://www.dtcms.com/a/371641.html

相关文章:

  • [Android]RecycleView的item用法
  • 构建高可用二级缓存系统
  • hardhat3 框架源码修改后如何使用
  • Photoshop - Photoshop 创建文档
  • 论文阅读:SaTML 2023 A Light Recipe to Train Robust Vision Transformers
  • RocketMQ为什么自研Nameserver而不用zookeeper?
  • 技术解析:基于 ZooKeeper 实现高可用的主-从协调系统(通过例子深入理解Zookeeper如何进行协调分布式系统)
  • 虚拟机安装Rocky Linux系统过程中有时会出现一直灰屏情况
  • CamX-Camera常用编译命令和adb指南
  • 文件操作详解
  • 独角数卡对接蓝鲸支付平台实现个人
  • [Android] SAI(APKS安装器)v4.5
  • MySQL 主从读写分离架构
  • 软件可靠性基本概念
  • 无人机自组网系统的抗干扰技术分析
  • 对比Java学习Go——基础理论篇
  • centos9安装sentinel
  • 小迪安全v2023学习笔记(七十九讲)—— 中间件安全IISApacheTomcatNginxCVE
  • 关键字 const
  • 性能优化——首屏优化
  • Linux网络设备驱动程序深度理解
  • Unity AssetBundle详解
  • 小白AIGC短视频生成的第一课之混元AI视频
  • 通义万相wan2.2视频模型的基础模型与安装应用详解
  • JavaEE 进阶第三期:开启前端入门之旅(三)
  • Linux:NTP服务
  • 【多模态学习】QA3:FFN的作用?Embedding生成方法的BERT和Word2Vec?非线性引入的作用?
  • Tomcat 日志文件名的命名规范
  • 基于单片机的可燃性气体泄漏智能报警系统
  • Ubuntu系统下Python连接国产KingbaseES数据库实现增删改查