转载来自:http://blog.****.net/ahuier/article/details/10364757,并进行扩充
引言:Android开发中的数据存储方式
Android提供了5种方式存储数据:
1. 文件存储数据 [也就是通常说的SD卡中]
2. 使用SharedPreferences存储数据 (共享参数)
3. SQLite数据库存储数据
4. 使用ContentProvider存储数据 (内容提供器)
5. 网络存储数据 [可以把本地的数据存储在网络的服务端]
一:文件存储简介
Java提供了一套完整的IO流体系,包括FileInputStream和FileOutputStream等,通过这些类我们可以方便的访问磁盘上的文件内容,Android同样支持这种方式访问手机存储器上的文件。
Android上下文提供了如下两个方法来打开应用程序的数据文件夹里的文件IO流:
1)FileInputStream openFileInput(String name):打开应用程序的数据文件夹下的name文件对应的输入流
2) FileOutStream openFileOutput(Stringname,int mode):打开应用程序的数据文件夹下的name文件对应输出流
mode : 指定打开文件的模式,该模式支持如下值
Context.MODE_PRIVATE = 0
Context.MODE_APPEND = 32768 \\追加
Context.MODE_WORLD_READABLE = 1 \\可读
Context.MODE_WORLD_WRITEABLE = 2 \\可写
以上两个方法都是分别打开文件输入流、输出流,除此之外,Context还提供了如下几个方法来访问应用程序的数据文件夹:
getDir(String name,int mode) : 在应用程序的数据文件夹下获取或者创建name对应的子目录
FilegetFilesDir() : 获取该应用程序的数据文件夹的绝对路径
String[]fileList() : 返回该应用程序的数据文件夹下的指定文件
二:文件存储步骤
1) 在对SD卡进行操作的时候,必须在AndroidManifest.xml清单文件中添加它的授权,在AndroidManifest.xml下的Permissions标签下添加,如下图所示:
2) 进行单元测试,在AndroidManifest.xml下的Instrumentation标签下添加 单元测试,测试内容只需要添加测试名称和包的内容即可,如下图所示:
同时在AndroidManifest.xml 代码中加一个单元测试的标签就可以进行单元测试的内容了:
<uses-libraryandroid:name="android.test.runner"/>
3) AndroidManifest.xml代码如下:
[html] view
plaincopy
1.
<?xml version="1.0" encoding="utf-8"?>
2.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3.
package="com.android.sdcarddemo"
4.
android:versionCode="1"
5.
android:versionName="1.0" >
6.
7.
<uses-sdk
8.
android:minSdkVersion="8"
9.
android:targetSdkVersion="17" />
10.
<!-- 添加读写SD card 的授权 -->
11.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
12.
13.
<instrumentation
14.
android:name="android.test.InstrumentationTestRunner"
15.
android:targetPackage="com.android.sdcarddemo" >
16.
</instrumentation>
17.
18.
<application
19.
android:allowBackup="true"
20.
android:icon="@drawable/ic_launcher"
21.
android:label="@string/app_name"
22.
android:theme="@style/AppTheme" >
23.
<uses-library android:name="android.test.runner"/>
24.
<activity
25.
android:name="com.android.sdcarddemo.MainActivity"
26.
android:label="@string/app_name" >
27.
<intent-filter>
28.
<action android:name="android.intent.action.MAIN" />
29.
30.
<category android:name="android.intent.category.LAUNCHER" />
31.
</intent-filter>
32.
</activity>
33.
</application>
34.
35.
</manifest>
4) 布局文件 activity_main.xml
[html] view
plaincopy
1.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2.
xmlns:tools="http://schemas.android.com/tools"
3.
android:layout_width="match_parent"
4.
android:layout_height="match_parent"
5.
android:paddingBottom="@dimen/activity_vertical_margin"
6.
android:paddingLeft="@dimen/activity_horizontal_margin"
7.
android:paddingRight="@dimen/activity_horizontal_margin"
8.
android:paddingTop="@dimen/activity_vertical_margin"
9.
tools:context=".MainActivity" >
10.
11.
<EditText
12.
android:id="@+id/editText1"
13.
android:layout_width="wrap_content"
14.
android:layout_height="wrap_content"
15.
android:layout_alignParentLeft="true"
16.
android:layout_alignParentTop="true"
17.
android:layout_marginLeft="21dp"
18.
android:layout_marginTop="18dp"
19.
android:ems="10" >
20.
</EditText>
21.
22.
<Button
23.
android:id="@+id/button2"
24.
android:layout_width="wrap_content"
25.
android:layout_height="wrap_content"
26.
android:layout_alignBaseline="@+id/textView1"
27.
android:layout_alignBottom="@+id/textView1"
28.
android:layout_alignLeft="@+id/button1"
29.
android:text="读取信息" />
30.
31.
<TextView
32.
android:id="@+id/textView1"
33.
android:layout_width="wrap_content"
34.
android:layout_height="wrap_content"
35.
android:layout_below="@+id/button1"
36.
android:layout_centerHorizontal="true"
37.
android:layout_marginTop="40dp" />
38.
39.
<Button
40.
android:id="@+id/button1"
41.
android:layout_width="wrap_content"
42.
android:layout_height="wrap_content"
43.
android:layout_alignLeft="@+id/editText1"
44.
android:layout_below="@+id/editText1"
45.
android:layout_marginTop="20dp"
46.
android:text="保存信息" />
47.
48.
</RelativeLayout>
5) FileService.java 服务类,用来实现读写SD卡的方法
[java] view
plaincopy
1.
package com.android.sdcarddemo;
2.
3.
import java.io.ByteArrayOutputStream;
4.
import java.io.File;
5.
import java.io.FileInputStream;
6.
import java.io.FileNotFoundException;
7.
import java.io.FileOutputStream;
8.
import java.io.IOException;
9.
10.
import android.content.Context;
11.
import android.os.Environment;
12.
import android.util.Log;
13.
import android.widget.Toast;
14.
15.
public class FileService {
16.
17.
private final static String TAG = "FileService";
18.
private Context context;
19.
20.
public FileService(Context context) {
21.
this.context = context;
22.
}
23.
24.
public FileService() {
25.
}
26.
27.
public String getFileFromSdcard(String fileName) {
28.
FileInputStream inputStream = null;
29.
// 在手机应用开发中 ByteArrayOutputStream 流是缓冲的流,和磁盘无关,可以不需要关闭
30.
// Environment.MEDIA_MOUNTED 如果是可读写的状态,并且SD卡是存在的情况下
31.
ByteArrayOutputStream outputSteam = new ByteArrayOutputStream();
32.
File file = new File(Environment.getExternalStorageDirectory(), fileName);
33.
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
34.
try {
35.
inputStream = new FileInputStream(file);
36.
;
37.
];
38.
!= (length = (inputStream.read(buffer)))) {
39.
outputSteam.write(buffer, , length);
40.
}
41.
42.
} catch (FileNotFoundException e) {
43.
// TODO Auto-generated catch block
44.
e.printStackTrace();
45.
} catch (IOException e) {
46.
// TODO Auto-generated catch block
47.
e.printStackTrace();
48.
} finally {
49.
if (inputStream != null) {
50.
try {
51.
inputStream.close();
52.
} catch (IOException e) {
53.
// TODO Auto-generated catch block
54.
e.printStackTrace();
55.
}
56.
}
57.
}
58.
} else {
59.
Toast.makeText(context, "Please input SD card", Toast.LENGTH_LONG).show();
60.
Log.i(TAG, "No SD card");
61.
}
62.
63.
return new String(outputSteam.toByteArray());
64.
}
65.
66.
/**
67.
* 把内容保存在SD 卡上
68.
*
69.
* @param fileName 文件的名称
70.
* @param content 文件的内容
71.
* @return
72.
*/
73.
public boolean saveContentToSDcard(String fileName, String content) {
74.
boolean flag = false;
75.
FileOutputStream fileOutputStream = null;
76.
// 获得SD卡的路径
77.
File file = new File(Environment.getExternalStorageDirectory(), fileName);
78.
// 判断SD卡是否可以用
79.
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageDirectory())) {
80.
try {
81.
fileOutputStream = new FileOutputStream(file);
82.
fileOutputStream.write(content.getBytes());
83.
flag = true;
84.
} catch (FileNotFoundException e) {
85.
// TODO Auto-generated catch block
86.
e.printStackTrace();
87.
} catch (IOException e) {
88.
// TODO Auto-generated catch block
89.
e.printStackTrace();
90.
} finally {
91.
if (fileOutputStream != null) {
92.
try {
93.
fileOutputStream.close();
94.
} catch (IOException e) {
95.
// TODO Auto-generated catch block
96.
e.printStackTrace();
97.
}
98.
}
99.
}
100.
}
101.
102.
return flag;
103.
}
104.
}
6) 主程序文件 MainActivity.java
[java] view
plaincopy
1.
package com.android.sdcarddemo;
2.
3.
import android.os.Bundle;
4.
import android.app.Activity;
5.
import android.content.Context;
6.
import android.util.Log;
7.
import android.view.Menu;
8.
import android.view.View;
9.
import android.view.View.OnClickListener;
10.
import android.widget.Button;
11.
import android.widget.EditText;
12.
import android.widget.TextView;
13.
14.
public class MainActivity extends Activity {
15.
16.
private static final String TAG = "MainActivity";
17.
18.
private Button button;
19.
private Button button1;
20.
private EditText editText;
21.
private TextView textView;
22.
23.
@Override
24.
protected void onCreate(Bundle savedInstanceState) {
25.
super.onCreate(savedInstanceState);
26.
setContentView(R.layout.activity_main);
27.
initComponent();
28.
button.setOnClickListener(new OnClickListener() {
29.
30.
@Override
31.
public void onClick(View v) {
32.
// TODO Auto-generated method stub
33.
MainActivity.this.saveFile();
34.
}
35.
});
36.
37.
button1.setOnClickListener(new OnClickListener() {
38.
39.
@Override
40.
public void onClick(View v) {
41.
// TODO Auto-generated method stub
42.
MainActivity.this.readFile();
43.
}
44.
});
45.
}
46.
47.
@Override
48.
public boolean onCreateOptionsMenu(Menu menu) {
49.
// Inflate the menu; this adds items to the action bar if it is present.
50.
getMenuInflater().inflate(R.menu.main, menu);
51.
return true;
52.
}
53.
54.
private void initComponent(){
55.
button = (Button)findViewById(R.id.button1);
56.
button1 = (Button)findViewById(R.id.button2);
57.
editText = (EditText)findViewById(R.id.editText1);
58.
textView = (TextView)findViewById(R.id.textView1);
59.
60.
}
61.
62.
private void saveFile(){
63.
String str = editText.getText().toString();
64.
FileService fileService = new FileService();
65.
boolean flag = fileService.saveContentToSDcard("hello.txt", str);
66.
Log.i(TAG, "------->> " + flag);
67.
}
68.
69.
private void readFile(){
70.
FileService fileService = new FileService(MainActivity.this);
71.
String str = fileService.getFileFromSdcard("hello.txt");
72.
textView.setText(str);
73.
}
74.
75.
}
程序运行结果:
略
扩展:
(1)直接从一个文件进行读写,而不是使用editText控件,该怎么实现?
使用 Context类生成对象进行上下文传递
(2)单独建立一个MyTest.java类文件进行单元测试会较好
三:文件存储过程总结
(1)从sdcard上读取文件
判断File是否在sdcard上->建立FileInputStream(new File())对象 ->调用new FileInputStream()对象的read方法读取信息->调用new ByteArrayOutputStream()缓冲流对象的的write方法写入缓冲区中->调用new String(outputStream.toByteArray())对象将缓冲区内容转化为字符串格式
(2)向sdcard保存文件
通过Environment.getExternalStorageDirectory()获得sdcard路径->通过new File(文件路径,文件名称)建立文件->判断sdcard是否可用Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageDirectory())->调用new FileOutputStream(new File())的write方法
四:知识点扩充Environment
Environment类[查看AndroidAPI文档]:这个类提供了一些操作系统环境应用的操作,在这里面的
Constants 里面的返回值可以判断出SD卡的状态:装载、卸载、或者是允许可读写的操作
如下图所示:
File file = new File(Environment.getxxxx); //得到扩展存储卡的路径
Eclipse使用技巧:方法前面自动增加注释快捷键是 alt+shift+j