Android存储之——文件存储
文件存储记好一个方法openFileOutput()
返回值为FileOutputStream对象
两个参数:
参数一:要保存的文件名字
如”FileName.txt”,注意不要写目录,它有默认的目录下,data/data/包名/files/下
参数二:文件的操作模式。
主要有两种模式:Context.MODE_PRIVATE 和 MODE_APPEND,默认为MODE_PRIVATE,同名时会被覆盖;MODE_APPEND同名时会追加。还有两种不安全的模式允许其他程序对其操作,极其不安全,在Android 4.20之后被废弃了。
openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。
创建的文件保存在/data/data/<package name>
/files目录,如: /data/data/cn.itcast.action/files/itcast.txt ,通过点击Eclipse菜单“Window”-“Show View”-“Other”,在对话窗口中展开android文件夹,选择下面的File Explorer视图,然后在File Explorer视图中展开/data/data/<package name>
/files目录就可以看到该文件。
openFileOutput()方法的第二参数用于指定操作模式,有四种模式,分别为:
Context.MODE_PRIVATE = 0
Context.MODE_APPEND = 32768
Context.MODE_WORLD_READABLE = 1
Context.MODE_WORLD_WRITEABLE = 2
Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND
Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。
MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;
MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。
如果希望文件被其他应用读和写,可以传入: openFileOutput(“itcast.txt”, Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); android有一套自己的安全模型,当应用程序(.apk)在安装时系统就会分配给他一个userid,当该应用要去访问其他资源比如文件的时候,就需要userid匹配。默认情况下,任何应用创建的文件,sharedpreferences,数据库都应该是私有的(位于/data/data/<package name>
/files),其他程序无法访问。
除非在创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE ,只有这样其他程序才能正确访问。
下面例子是一个存储EditText中输入内容的例子,在EditText按返回键销毁前保存数据,重写onDestory()方法。
xml布局文件中的代码:
<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" >
<EditText android:id="@+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入你要存储的内容" />
</LinearLayout>
MainActivity中代码:
package org.day13_filesave;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.widget.EditText;
public class MainActivity extends Activity {
EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 得到输入内容
String data = editText.getText().toString();
save(data, "fileName.txt");
}
public void save(String data, String name) {
FileOutputStream fos = null;
BufferedWriter bw = null;
try {
/** * @return 返回值 为FileOutputStream * @parmas 参数一:指的是要存储的文本的名字,不要写包名 ,有默认的目录 data/data/<package>/files/ * @parmas 参数二:操作模式,一般默认选用Context.MODE_PRIVATE * 出现同名时直接覆盖,还有一种是MODE_APPEND追加 */
fos = openFileOutput(name, Context.MODE_PRIVATE);
// 利用缓冲流写入,中间使用了转换流将字节流转换成字符流
bw = new BufferedWriter(new OutputStreamWriter(fos));
bw.write(data);
bw.flush();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
下面就增加一点难度,实现下次打开时候,输入框直接显示上次输入的内容。类似于QQ空间发表说说时候来电话了 后来接完电话就关机睡觉,第二天打开发表说说还是前一天编辑一半的内容,并不清空。
这中间有一个读取存储数据的过程,引出另外一个方法openFileInput(),返回值是FileInputStream,参数只有一个,是存储的文件名,依旧不要包名,它去默认目录库下找。
xml布局文件代码不变,参考上面;
MainActivity中代码如下:
package org.day13_filesave;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 加载布局
setContentView(R.layout.activity_main);
// 初始化控件
initViews();
}
// 在初始化时完成EditText上次输入内容的读取
private void initViews() {
editText = (EditText) findViewById(R.id.editText);
// 读取上次存储的内容
String inputText = load("fileName.txt");
// 调用TextUtils.isEmpty()方法实现两种判断,是否为""和 是否为null。
if (!TextUtils.isEmpty(inputText)) {
editText.setText(inputText);
// 设置光标位置位于读取到的字符串的末尾
editText.setSelection(inputText.length());
Toast.makeText(this, "恢复数据成功!", 0).show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// 得到输入内容
String data = editText.getText().toString();
save(data, "fileName.txt");
}
public void save(String data, String fileName) {
FileOutputStream fos = null;
BufferedWriter bw = null;
try {
/** * @return 返回值 为FileOutputStream * @parmas 参数一:指的是要存储的文本的名字,不要写包名 ,有默认的目录 data/data/<package>/files/ * @parmas 参数二:操作模式,一般默认选用Context.MODE_PRIVATE * 出现同名时直接覆盖,还有一种是MODE_APPEND追加 */
fos = openFileOutput(fileName, Context.MODE_PRIVATE);
// 利用缓冲流写入,中间使用了转换流将字节流转换成字符流
bw = new BufferedWriter(new OutputStreamWriter(fos));
bw.write(data);
bw.flush();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 此处不必关闭fos,因为bw封装了fos,一旦外层封装流bw关闭了,内部的fos自然就关闭了
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
// 读取上次保存的内容
public String load(String fileName) {
FileInputStream fis = null;
BufferedReader br = null;
StringBuilder content = new StringBuilder();// StringBuilder:是线程不安全的,比StringBuffer效率高
try {
/** * @return 返回值为一个FileInputStream对象 * @param 参数为要打开文件名字 * ,不用包名它去默认的路径下面查找 * */
fis = openFileInput(fileName);
br = new BufferedReader(new InputStreamReader(fis));
String line = "";
while ((line = br.readLine()) != null) {
content.append(line);// 拼接到字符串缓冲区
}
// 返回值转换成String 方便setText用
return content.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
还没有评论,来说两句吧...