手机自带内存较小,不适合存储大量数据,一般,大量数据都会采用外部存储,如:服务器存储、SD卡存储、数据库存储等。
本文讲解在SD卡上存储数据,并实现对数据的读和写。
整体思路:静态权限声明、动态权限请求、布局、编写逻辑进行测试,找到文件所处位置
第1步:声明静态权限,外部存储的读和写权限
具体操作:在AndroidManifest.xml中增加两行配置
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
第2步:在onCreate回调函数中,动态请求权限
具体操作:版本是23以后,需要动态请求权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
/*新API要求,23以后版本要求先授权,才能访问,一次授权后,后面就无需再授权*/
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
Toast.makeText(this, "获取权限", Toast.LENGTH_SHORT).show();
} else {
/*旧API*/
Toast.makeText(this, "没有权限", Toast.LENGTH_SHORT).show();
}
第3步:设计布局
思路:两个按钮,别人实现读和写,一个输入框,实现用户输入的内容,通过写按钮,存储到SD卡对应的文件中;一个文本框,通过读按钮,实现将SD卡文件中的内容读取出来并显示
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="显示数据"/>
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入测试数据"/>
<Button
android:id="@+id/writeBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="写入"/>
<Button
android:id="@+id/readBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="读取"/>
</LinearLayout>
第4步:逻辑文件
整体思路:声明属性、绑定组件、实现按钮监听事件、实现读和写
(1)声明属性
Button readBtn, writeBtn;
TextView textView;
EditText editText;
(2)绑定组件
readBtn = findViewById(R.id.readBtn);
writeBtn = findViewById(R.id.writeBtn);
editText = findViewById(R.id.editText);
textView = findViewById(R.id.textView);
(3)实现按钮监听事件
readBtn.setOnClickListener(this);
writeBtn.setOnClickListener(this);
(4)实现读和写
public void onClick(View v) {
int id = v.getId();
if (id == R.id.writeBtn) {
/*获取SD卡目录*/
File sdDir = getFilesDir();
System.out.println(sdDir.toString());
try {
/*根据目录和文件名创建文件*/
File file = new File(sdDir.getCanonicalPath() + "/" + FILENAME);
/*创建RandomAccessFile对象,用于文件操作*/
RandomAccessFile raf = new RandomAccessFile(file, "rw");
/*将指针移动到文件末尾,表示偏移量,设置在末尾或者末尾以外的地方,才能进行写,从而改变文件长度*/
raf.seek(file.length());
/*将内容写入文件*/
String writeContent = editText.getText().toString();
raf.write(writeContent.getBytes());
raf.close();
Toast.makeText(this, "【保存的数据是】" + writeContent,
Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "异常咯", Toast.LENGTH_SHORT).show();
}
} else if (id == R.id.readBtn) {
File sdDirRead = getFilesDir();
try {
FileInputStream fis = new FileInputStream(sdDirRead.getCanonicalPath() + "/" + FILENAME);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
StringBuilder sb = new StringBuilder();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
String readContent = sb.toString();
textView.setText(readContent);
Toast.makeText(this, "【读取到的数据是】" + readContent, Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
写操作思路:
- 先要通过getFilesDir()方法获取到SD卡目录
- 然后根据目录和文件名创建指定的文件
- 创建RandomAccessFile对象,用于文件操作
- 获取用户输入的内容,并转换为指定格式,使用RandomAccessFile对象的write方法进行写入
- 关闭文件操作
- 处理提示信息以及展示
读操作思路:
- 先要通过getFilesDir()方法获取到SD卡目录
- 通过文件输入流读取内容
- 并将读取到的内容展示到UI界面并给与一定提示
需要注意的是:
Android 11以前的外存空间获取目录的方法为:
Environment.getExternalStorageDirectory()
Android 11以后得版本获取目录的方法是:
getFilesDir();
第5步:测试
SD卡读写效果
第6步:找到创建的文件对应的存储位置
查看程序打印的存储路径:
/data/user/0/com.yibinu.sddemo/files
找对应的位置