Android开发笔记(二十二)——数据存储之文件存储
文件存储是利用Java的I/O流来实现向Android硬件磁盘上进行读写的操作。
Android存储概念
内部存储 Internal Storage :不可更改的,随着应用的卸载被删除
内部存储的特点:
- 默认只能被创建它的应用访问到
- 当这个应用卸载后,内部存储中的文件也被删除
- 一旦内部存储空间耗尽,手机也就无法使用
/data/data/<applicationId>/shard_prefs
/data/data/<applicationId>/databases
/data/data/<applicationId>/files
/data/data/<applicationId>/cache
这四个文件夹都是属于内部存储。
前两个文件是通过系统提供的类和方法来获得文件的内容。
后两个文件是通过 context.getCacheDir()
和 context.getFilesDir()
这两个方法来得到。
外部存储 External Storage :可更改的。分为公有目录和私有目录,
公有目录:通过 Environment.getExternalStoragePublicDirectory(int type)
方法来获得公有目录下对应类型的文件。
私有目录:随着应用的卸载被删除
/mnt/sdcard/data/data/<applicationId>/files
/mnt/sdcard/data/data/<applicationId>/cache
File内部存储
比较重要的两个类: FileOutputStream
、 FileInputStream
。
代码示例:
FileActivity的java文件:
public class FileActivity extends AppCompatActivity {
private EditText mEtName;
private Button mBtnSave,mBtnShow;
private TextView mTvContent;
private final String mFinalName = "text.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file);
mEtName=findViewById(R.id.et_name);
mBtnSave=findViewById(R.id.btn_save);
mBtnShow=findViewById(R.id.btn_show);
mTvContent=findViewById(R.id.tv_content);
mBtnSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
save(mEtName.getText().toString().trim()); //trim()表示去除前后空格,没有也可以
}
});
mBtnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTvContent.setText(read());
}
});
}
//存储数据
private void save(String content){
FileOutputStream fileOutputStream=null;
try {
//创建存储目标
fileOutputStream = openFileOutput(mFinalName,MODE_PRIVATE);
//字节方式存储方法
fileOutputStream.write(content.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
if (fileOutputStream!=null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//读取数据
private String read(){
FileInputStream fileInputStream = null;
try {
//获取读取文件
fileInputStream = openFileInput(mFinalName);
//设置一次读取字节数
byte[] buff = new byte[1024];
//获取StringBuilder,实现字符串拼接
StringBuilder sb = new StringBuilder("");
int len = 0;
//循环读取
while ((len = fileInputStream.read(buff)) > 0){
sb.append(new String(buff,0,len));
}
//返回读取数据
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
if (fileInputStream!=null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="15dp">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入内容"
/>
<Button
android:id="@+id/btn_save"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="保存"
android:layout_marginTop="10dp"
/>
<Button
android:id="@+id/btn_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="显示"
android:layout_marginTop="10dp"
/>
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
/>
</LinearLayout>
运行效果:
总结:
存储数据:
- 获取FileOutputStream对象
- 调用write()方法
- 调用close()方法
读取数据:
- 获取FileInputStream对象
- 调用read()方法
- 调用close()方法
File外部存储
在SD中新建一个文件夹,在这个文件夹中新建一个文件,然后写入一些内容再读取出来。
和内部存储原理是相同的,就是存储路径不同,一个在内部存储器上,一个在外部存储器。
代码示例:
public class FileActivity extends AppCompatActivity {
private EditText mEtName;
private Button mBtnSave,mBtnShow;
private TextView mTvContent;
private final String mFinalName = "text.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file);
mEtName=findViewById(R.id.et_name);
mBtnSave=findViewById(R.id.btn_save);
mBtnShow=findViewById(R.id.btn_show);
mTvContent=findViewById(R.id.tv_content);
mBtnSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
save(mEtName.getText().toString().trim()); //trim()表示去除前后空格
}
});
mBtnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTvContent.setText(read());
}
});
}
//存储数据
private void save(String content){
FileOutputStream fileOutputStream=null;
try {
// //外部存储
// fileOutputStream = openFileOutput(mFinalName,MODE_PRIVATE);
//内部存储
//创建文件夹
File dir = new File(Environment.getExternalStorageState(),"FileStorage");
if (!dir.exists()) {
dir.mkdirs();
}
//创建文件
File file = new File(dir,mFinalName);
if (!file.exists()) {
file.createNewFile();
}
fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(content.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOutputStream!=null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//读取数据
private String read(){
FileInputStream fileInputStream = null;
try {
// //内部存储
// fileInputStream = openFileInput(mFinalName);
//外部存储
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"FileStorage",mFinalName);
fileInputStream = new FileInputStream(file);
byte[] buff = new byte[1024];
//实现字符串拼接
StringBuilder sb = new StringBuilder("");
int len = 0;
while ((len = fileInputStream.read(buff)) > 0){
sb.append(new String(buff,0,len));
}
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileInputStream!=null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
布局文件和上面的一样:
此外要在AndroidManifest.xml里添加两行代码,用来获取存储权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
这里在真机上运行出现如需下错误:
暂时没有解决。