《第一行代码》第二版 学习总结11 数据持久化之本地文件存储
最近利用下班时间,找了看什么书比较适合初学android的朋友,很多人推荐了这本书,于是就买了一本,感觉看书,思考,动手,再思考和总结这样过程还是很有必要的,于是就打算把自己学习的东西简单的总结一下;方便自己以后查找,也有利于学习的巩固。在这里首先要感谢一下书籍的作者——郭霖前辈。
本篇开始与接下来的三篇以及一个附篇都会介绍一下Android系统中数据持久化的基本内容,本章主要介绍通过本地文件的方式来存储数据。由于把数据存储在SD卡中相对比较繁琐和危险,所以我会放在附篇中介绍。这里介绍的通过本地文件存储数据应该说是Android中的一种最基本的方式了。它对要存储的数据不做任何处理;所以常常用于存储一些比较简单的文本数据;对于一些复杂的数据;考虑后期取出的时候解析过于麻烦,通常不采用这种方式。
1,基本概念与要点
- Context类中提供一个openFileOutput()方法,用于存储数据到指定文件;它接受两个参数,第一个文件名称,第二个保存的方式;默认的保存路径为data/data/<packagename>/files目录下
- Context类中提供一个openFileInput()方法,用于读取指定文件数据;它接受一个参数,就是文件名称
对于这两个方法,返回的都是一个流对象,前者是输出流,后者是一个输入流;指向上面已经说了。所以这种方式保存数据是非常简单的;下面就来看看具体的使用吧。
2,代码示例
AppFileActivity.java代码:
package com.hfut.operationappfile;
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; public class AppFileActivity extends AppCompatActivity { EditText editFileName; EditText fileContent; TextView readFileContent; Button saveButton; Button readButton; Button editButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_app_file); initUI(); } private void initUI() { editFileName = findViewById(R.id.editFileName); fileContent = findViewById(R.id.editFileContent); readFileContent = findViewById(R.id.readFileContent); saveButton = findViewById(R.id.saveFile); editButton = findViewById(R.id.editFile); readButton = findViewById(R.id.readFile); } // @Override // public void onClick(View v) { // switch (v.getId()) { // case R.id.saveFile: // saveFile(); // break; // case R.id.readFile: // readFile(); // break; // case R.id.editFile: // editFile(); // break; // default: // break; // // } // } public void save(View view) { saveFile(); fileContent.setText(""); editFileName.setText(""); fileContent.setHint("请输入要保存数据"); editFileName.setHint("请输入文件名称"); } public void read(View view) { readFile(); } public void edit(View view) { editFile(); } /** * 下面保存文件数据和读取文件数据其实包的异常都是一样的,这里我给了不同的处理 * 在编辑文件的时候,我自己用IOException涵盖了FileNotFoundException * 在读取文件的时候,我保留了原样 * 还有一个编辑上一次保存的文件数据,加了一个光标定位; */ //编辑数据 private void saveFile() { String fileName = editFileName.getText().toString(); if (TextUtils.isEmpty(fileName)) { readFileContent.setText("请您先输入要查看的文件名称"); } else { String tempfileContent = fileContent.getText().toString(); BufferedWriter writer = null; //以MODE_PRIVATE形式,还可以以MODE_APPEND,自己可以试一试 try { OutputStream out = openFileOutput(fileName, MODE_PRIVATE); // OutputStream out=openFileOutput(fileName,MODE_APPEND); //对输出流两次包装;字节流--字符流--字符缓冲流 writer = new BufferedWriter(new OutputStreamWriter(out)); writer.write(tempfileContent); readFileContent.setText(editFileName.getText().toString()+"保存成功,可以点击读取文件查看"); } catch (IOException e) { e.printStackTrace(); } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } } } } //读取数据 private void readFile() { String fileName = editFileName.getText().toString(); if (TextUtils.isEmpty(fileName)) { readFileContent.setText("请您先输入要查看的文件名称"); } else { StringBuilder stringBuilder = new StringBuilder(); try { InputStream in = openFileInput(fileName); //两次包装,同上 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String readLineContent = ""; try { while ((readLineContent = reader.readLine()) != null) { stringBuilder.append(readLineContent); } readFileContent.setText(fileName + "中的数据是:\n"); readFileContent.append(stringBuilder.toString()); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } } catch (FileNotFoundException e) { readFileContent.setText("对不起,您输入的文件不存在,请重新输入"); e.printStackTrace(); } } } //编辑上次保存或者编辑的数据 private void editFile() { readFileContent.setText("你现在可以对文件数据进行修改编辑了,别忘了修改之后记得保存哟!"); String fileName = editFileName.getText().toString(); StringBuilder stringBuilder = new StringBuilder(); try { InputStream in = openFileInput(fileName); //两次包装,同上 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String readLineContent = ""; try { while ((readLineContent = reader.readLine()) != null) { stringBuilder.append(readLineContent); } } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } } catch (FileNotFoundException e) { readFileContent.setText("对不起,您输入的文件不存在,请重新输入"); e.printStackTrace(); } fileContent.setText(stringBuilder.toString()); if (!TextUtils.isEmpty(stringBuilder.toString())) { fileContent.setSelection(stringBuilder.toString().length()); } } }
activity_app_file.xml代码:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.hfut.operationappfile.AppFileActivity"> <EditText android:layout_marginTop="30dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/editFileName" android:hint="请输入文件名称"/> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/editFileContent" android:hint="请输入要保存数据"/> <LinearLayout android:layout_marginTop="20dp" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:onClick="save" android:id="@+id/saveFile" android:text="保存文件" android:layout_marginTop="10dp" android:layout_marginLeft="150dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:onClick="read" android:id="@+id/readFile" android:text="读取文件" android:layout_marginTop="10dp" android:layout_marginLeft="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:onClick="edit" android:id="@+id/editFile" android:text="编辑文件" android:layout_marginTop="10dp" android:layout_marginLeft="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <TextView android:layout_marginTop="20dp" android:textSize="15dp" android:id="@+id/readFileContent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="显示读取文件的数据" /> </LinearLayout>
主配置文件AndroidManifest.xml代码:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.hfut.operationappfile"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".AppFileActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
3,运行结果
第一步:运行程序
图 1
第二步:不输入任何数据,点击任意一个按钮
图 2
第三步:输入一个文件名称,并输入在该文件中要保存的数据
图 3
第四步:点击保存
图 4
第五步:输入刚刚保存的文件名称,点击“读取文件”按钮
图 5
第六步:再点击“编辑文件”按钮
图 6
第七步:重新编辑上次存储的文本内容,然后点击“保存文件”按钮
图 7
第八步:点击“读取文件”按钮
图 8
第九步:输入一个其他的文件名称,并点击“读取文件”或者“编辑文件”按钮
图 9
第十步:打开/data/data/下的app应用包,会发现多了一个files文件夹,并且里面有一个why.txt文件,内容如下图:
图 10
总结:这部分总得来说还是很简单的,也没有需要特别说明的地方,在openFileOutput()的第二个参数中,我们这里使用的是
MODE_PRIVATE,你也可以试试另一个MODE_APPEND;我在代码中也都写了,只要取消注释就可以,这个append和StringBuffer和StringBiulder中的append()方法含义一样,就是在文件后面追加这些数据;而不是像第一个覆盖原有数据。好了,这一部分到这里就说完了。再见了