转载来自:http://blog.csdn.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. int length = 0;
37. byte[] buffer = new byte[1024];
38. while (-1 != (length = (inputStream.read(buffer)))) {
39. outputSteam.write(buffer, 0, 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