在软件开发中很多情况都需要用到数据的存储,Android中存数据和取数据与Java是相似的,都需要使用流的机制。可以将数据存储到手机内存、SD卡和网络端。
Android中较为常用的是java.io.FileOutputStream和java.io.FileInputStream这一对流类,同样也需要通过File类来构造一个具体指向文件或文件夹以便操作的对象,不同的是Android中不通过新建流的类来指定文件,而是通过openFileOutput()方法和openFileInput()方法来获取流,不需要指定文件存储的位置,但需要指定文件名,文件被存储在应用程序私有的存储数据目录中/data/data/包名/files/文件名,只有该程序有写入权限。
其中输出流需要为它设置打开模式,主要有以下模式
MODE_PRIVATE:该文件只能被当前程序读写(通常选择该项)
MODE_APPEND:以追加的方式打开该文件
MODE_WORLD_READABLE:该文件的内容可以被其他程序读取
MODE_WORLD_WRITEABLE:该文件的被人可由其他程序读写。
MODE_MULTI_PROCESS:设置多线程安全
(此外Context提供了如下几个方法来访问应用程序的数据文件夹
getDir(String name,int mode):获取或创建name对应的子目录
File getFilesDir():获取该应用程序的数据文件夹的绝对路径
String[] fileList():返回该应用程序的数据文件夹的全部文件
deleteFile(String):删除该应用程序的数据文件夹下的指定文件)
在读写文件到SD卡时需要进行SD卡是否可用判断,代码为
boolean b=Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
存入SD卡的位置亦是固定的,获取路径方法为
Environment.getExternalStorageDirectory()
想要对SD卡进行操作需要获取两项权限:
MOUNT_UNMOUNT_FILESYSTEMS:创建和删除文件权限
WRITE_EXTERNAL_STORAGE:写入数据权限
以上方法都是将存储内容以文本文件存在手机里,Android还有一种轻量级的存储方式,以xml文件的方式存储数据,Preferences是一种轻量级的数据存储机制,它将一些简单数据类型的数据,如boolean、int、float、long、String等以键值对的形式存储在应用程序私有Preferences目录中:data/data/包名/shared_prefs
由于Preferences的使用方便和数据简单,我们一般使用Preferences存储一些配置信息,如开关状态、音量等等,其安全性也无需考虑,被看到也无所谓。
Preferences的使用要通过SharedPreferences接口实现,该接口由Context. getSharedPreferences()方法获取,其中有两个参数:文件名,如果文件不存在将自动创建,打开模式。SharePreferences接口本身没有提供写入数据的能力,而是通过SharedPreferences
的内部接口Editor,获取方法为Editor editor =sharedPreferences.edit(),它有如下方法:
clear():清空所有数据
putXxx(Stringkey,Xxx value):存入指定key对应的数据(Xxx指数据类型如int等)
remove(Stringkey):删除指定key对应的数据项
commit():当Editor编辑完成后,调用该方法提交修改
从中读取的方法为
sharedPreferences.getString("con",null);第一个参数为key值,第二个参数为默认值,如果文件不存在或者key值不存在将返回默认值。同理还有getInt()、getBoolean()等。
以下对读写手机内存、SD卡和Preferences做一个简单测试,布局文件如下
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.briup.file.MainActivity" >
<EditText
android:id="@+id/file_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Plase input File name" />
<EditText
android:id="@+id/file_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Plase input File content" />
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="save"
android:text="SAVE" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="read"
android:text="READ" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="savesd"
android:text="SAVESD" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="readsd"
android:text="READSD" />
<ToggleButton
android:id="@+id/tb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textOff="关"
android:textOn="开" />
</LinearLayout>
MainActivity类文件如下
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
public class MainActivity extends Activity {
private EditText fileName, fileContent;
private TextView text;
private ToggleButton tb;
private String name;
private String content;
private boolean flag = false;
private SharedPreferences sharedPreferences;//操作Preferences文件的类
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fileName = (EditText) findViewById(R.id.file_name);
fileContent = (EditText) findViewById(R.id.file_content);
text = (TextView) findViewById(R.id.text);
tb = (ToggleButton) findViewById(R.id.tb);
//获得SharedPreferences对象,(文件名,打开模式)
sharedPreferences = getSharedPreferences("isOff", Context.MODE_PRIVATE);
//通过key值获取值,第二个参数为默认值,如果文件不存在或者没有该key值将提供该值
tb.setChecked(sharedPreferences.getBoolean("isOff", false));
//点击开关按钮后改变开关状态并保存该状态
tb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
//需要借助Editor类
Editor editor = sharedPreferences.edit();
editor.putBoolean("isOff", isChecked);
editor.commit();
}
});
}
public boolean get() {
name = fileName.getText().toString();
content = fileContent.getText().toString();
if (name.equals(""))
flag = true;
return flag;
}
public void save(View v) {
//获取文本输入框内容并判空,在创建的文件时,不能没有文件名
if (get()) {
Toast.makeText(this, "FileName is null!",
Toast.LENGTH_SHORT).show();
} else {
FileOutputStream output = null;
try {
// 保存至手机内存位置"data/data/com.briup.file/files",应用卸载后该文件删除
output = openFileOutput(name, Context.MODE_PRIVATE);// Android自带的文件读写方法(文件名,文件访问格式),将文件保存在本应用程序文件夹下
output.write(content.getBytes("UTF-8"));// 设定编码类型,Linux默认编码为UTF-8
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Toast.makeText(MainActivity.this, "Saved success!",
Toast.LENGTH_SHORT).show();
}
}
public void read(View v) {
if (get()) {
Toast.makeText(this, "FileName is null!",
Toast.LENGTH_SHORT).show();
} else {
FileInputStream input = null;
BufferedReader reader = null;
StringBuffer buffer = new StringBuffer();// StringBuffer追加字符方便
try {
input = openFileInput(name);// 读取本应用程序下的文件(文件名)
reader = new BufferedReader(new InputStreamReader(input));
String msg = "";
while ((msg = reader.readLine()) != null) {
buffer.append(msg);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
text.setText(buffer);
}
}
public void savesd(View v) {
if (get()) {
Toast.makeText(this, "FileName is null!",
Toast.LENGTH_SHORT).show();
} else {
// 判断SD卡是否可用,手机中不一定有SD卡
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
FileOutputStream fos = null;
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath();// 获取SD卡绝对路径
try {
fos = new FileOutputStream(path + "/" + name);
fos.write(content.getBytes("UTF-8"));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Toast.makeText(MainActivity.this, "Saved success!",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "SD card is disable",
Toast.LENGTH_SHORT).show();
}
}
}
public void readsd(View v) {
if (get()) {
Toast.makeText(this, "FileName is null!",
Toast.LENGTH_SHORT).show();
} else {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
FileInputStream fis = null;
BufferedReader reader = null;
StringBuffer buffer = new StringBuffer();
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath();
try {
fis = new FileInputStream(path + "/" + name);
reader = new BufferedReader(new InputStreamReader(fis));
String msg = "";
while ((msg = reader.readLine()) != null) {
buffer.append(msg);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
text.setText(buffer);
} else {
Toast.makeText(MainActivity.this, "SD card is disable",
Toast.LENGTH_SHORT).show();
}
}
}
}
配置文件如下
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.briup.file"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="24" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.Holo.Light.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
效果如下
我们对手机内存和SD分别做写和读:
改变开关状态,退出返回发现初始加载即是改变过的状态