数据持久化

来源:互联网 发布:电气设计软件下载 编辑:程序博客网 时间:2024/05/16 05:12

在Android中,实现数据持久化主要有四种方式:Preferences,文件I/O,SQLite数据库,ContentProvider组件。

这里面讲的也很好:http://www.cnblogs.com/weixing/p/3243115.html

Preferences

Preferences是一种轻量级的数据存储机制,他将一些简单的数据类型的数据,包括boolean类型,int类型,float类型,long类型以及String类型的数据,以键值对的形式存储在应用程序的私有Preferences目录(/data/data/<包名>/shared_prefs/)中,这种Preferences机制广泛应用于存储应用程序中的配置信息。


SharedPreferences sharedPreferences = getSharedPreferences("ljq", Context.MODE_PRIVATE);//如果ljq不存在,则会自动新建

Editor editor = sharedPreferences.edit();//获取编辑器,然后就可以编辑它

editor.putString("name", "cjw");

editor.putInt("age", 4);

editor.commit();//提交修改

写入数据:

sPrefs = PreferenceManager.getDefaultSharedPreferences(context);

sPrefs.edit().putInt(SCREEN_COUNT, count).commit();


查看Preferences中的数据的方法有两种:

第一种是使用adb命令查看;

 

 

 

第二是使用DDMS——>FileExplorer在目录/data/data/<包名>/shared_prefs/中Preferences导出来查看。

如何访问其他应用中的Preference?


public void testAccessPreference2() throws Exception{
    Context context 
= this.getContext().createPackageContext("com.ljq.activity"
    Context.CONTEXT_IGNORE_SECURITY);
    SharedPreferences sharedPreferences 
= context.getSharedPreferences("ljq123"
    Context.MODE_WORLD_READABLE
+Context.MODE_WORLD_WRITEABLE);
    String name 
= sharedPreferences.getString("name""");
    int age = sharedPreferences.getInt("age"1);
    Log.i(TAG, name 
+ " : " +age);
}

2)文件I/O

1.使用内部存储器

创建:

  1. Call openFileOutput()
  1.  with the name of the file and the operating mode. This returns aFileOutputStream.
  1. Write to the file with write().
  1. Close the stream with close().
例如:
String FILENAME = "hello_file";
String string = "hello world!";

FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos
.write(string.getBytes());
fos
.close();
读取;
  1. Call openFileInput() 
  1. and pass it the name of the file to read. This returns a FileInputStream.
  1. Read bytes from the file with read().
  1. Then close the stream with close().
文件被保存在/data/data/包名/files
小技巧:
Tip: If you want to save a static file in your application at compile time, save the file in your project res/raw/directory. You can open it with openRawResource()
, passing the R.raw.<filename> resource ID. This method returns an InputStream that you can use to read the file (but you cannot write to the original file).比如QQ的提示音
有不懂可以看java学习笔记中的java IO。

使用缓存文件

不是永久存储,而是缓存数据,
you should use getCacheDir()to open a File that represents the internal directory where your application should save temporary cache files.

其他有用的方法

getFilesDir()
获取绝对路径到你的内部文件保存在文件系统中的目录。
GETDIR()
创建(或打开一个现有的),你的内部存储空间中的目录。
的DeleteFile()
删除保存在内部存储的文件。
fileList()
返回当前保存您的应用程序文件的数组

使用外部存储
1.声明权限:

为了读取或写入外部存储文件,您的应用程序必须获得 READ_EXTERNAL_STORAGE 或WRITE_EXTERNAL_STORAGE系统权限。例如:

<manifest ... > 
   
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
</manifest>

如果你需要同时读取和写入文件,那么你需要请求只有 WRITE_EXTERNAL_STORAGE权限,因为它隐含地要求读访问也是如此。

4.4之后私有的读取就不需要申明

2.Before you do any work with the external storage, you should always call getExternalStorageState() to check whether the media is available.

以下两个函数够用了,例如:
/* Checks if external storage is available for read and write 可读可写的检查*/
public boolean isExternalStorageWritable() {
   
String state = Environment.getExternalStorageState();// Environment提供环境变量的访问
   
if (Environment.MEDIA_MOUNTED.equals(state)) {
       
return true;
   
}
   
return false;
}

/* Checks if external storage is available to at least read只读的检查 */
public boolean isExternalStorageReadable() {
   
String state = Environment.getExternalStorageState();
   
if (Environment.MEDIA_MOUNTED.equals(state) ||
       
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
       
return true;
   
}
   
return false;
3.保存可共享给其他应用的文件
public File getAlbumStorageDir(String albumName) {
   
// Get the directory for the user's public pictures directory.
   
File file = new File(Environment.getExternalStoragePublicDirectory(
           
Environment.DIRECTORY_PICTURES), albumName);
   
if (!file.mkdirs()) {
       
Log.e(LOG_TAG, "Directory not created");
   
}
   
return file;
}

解释:调用getExternalStoragePublicDirectory()方法就是用来保存可共享给其他应用的文件, 其参数为DIRECTORY_MUSICDIRECTORY_PICTURES,DIRECTORY_RINGTONES,

4.保存私有的文件

调用getExternalFilesDir()方法解决,也含有参数,来指定目录的类型如:DIRECTORY_MOVIES,
首先也要指定权限:
<manifest ...>
   
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                     
android:maxSdkVersion="18" />
    ...
</manifest>
同样,由于4.4开始在私有的文件中读取就不需要指定权限,所以只需在19已下的才要指定,或者加入 maxSdkVersion属性;
已分配的内部存储器用作外部存储器的一个分区,又插入SD卡时,自带存储,又有SD卡槽的设备
4.3的设备getExternalFilesDir()方法,应用只能使用内部的存储,调用静态函数ContextCompat.getExternalFilesDirs()
4.3的设备:调用 getExternalFilesDirs()来获取一个文件数组,第一个基本的外部存储SD

5.外部保存缓存文件
调用getExternalCacheDir()方法,类似ContextCompat.getExternalFilesDirs() 
,上面提到的,你也可以通过调用访问的辅助外部存储(如果有的话)的缓存目录 ContextCompat.getExternalCacheDirs() 

Android平台主要通过Java.io.FileInputStream和java.io.FileOutputStream这两个类来实现对文件的读写,java.io.File类则用来构造一个具体指向某个文件或者文件夹的对象。

需要注意的是:每个应用程序所在的包都会有一个私有的存储数据的目录,只有属于这个包中的应用程序才有写入的权限,每个包中应用程序的私有数据目录位于 Android系统中的绝对路径/data/data/<package>/目录中,除了私有目录,应用程序还拥有/sdcard目录即 Android设备上的SD卡的写入权限。文件系统中其他的系统目录,第三方应用程序都是不可写的。

在我们RUI中,下载推荐应用时,就是在SD卡中建立一个目录,将下载的apk放入该目录中,具体的实现可以查看com.rui.mid.launcher.service.download中的FileUtil.java文件。在该文件中有一个changeMode方法改变文件的权限(可读,可写,可执行),就是为了能让系统调用该apk,实现应用的安装。

3)SQLite数据库

当应用程序需要处理的数据量比较大时,为了更加合理地存储、管理、查询数据,我们往往使用关系数据库来存储数据。Android平台为开发者提供了SQLite数据库相关的API来实现对数据库操作的支持,开发人员可以很方便的使用这些API来对SQLite数据库进行创建、修改及查询等操作。Android系统的很多用户数据,如联系人信息,通话记录,短信息等,都是存储在SQLite数据库当中的,所


以利用操作SQLite数据库的API可以同样方便的访问和修改这些数据。

在实际的应用程序编写中,为了更好的对SQlite数据的创建,打开,更改进行管理,往往会编写一个SQLiteOpenHelper的数据库辅助类来帮助我们创建和打开数据库。可以查考博客http://blog.csdn.net/rhljiayou/article/details/7085347

源码:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.example.usingpreference;  
  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.os.Bundle;  
  11. import android.app.Activity;  
  12. import android.content.Context;  
  13. import android.content.SharedPreferences;  
  14. import android.content.SharedPreferences.Editor;  
  15. import android.view.Menu;  
  16. import android.view.View;  
  17. import android.widget.Button;  
  18. import android.widget.EditText;  
  19. import android.widget.Toast;  
  20.   
  21. public class MainActivity extends Activity {  
  22.   
  23.     private EditText parem1;  
  24.     private EditText parem2;  
  25.     private Button save;  
  26.     private Button show;  
  27.   
  28.     @Override  
  29.     protected void onCreate(Bundle savedInstanceState) {  
  30.         super.onCreate(savedInstanceState);  
  31.         setContentView(R.layout.activity_main);  
  32.   
  33.         parem1 = (EditText) this.findViewById(R.id.editText1);  
  34.         parem2 = (EditText) this.findViewById(R.id.editText2);  
  35.         save = (Button) this.findViewById(R.id.button1);  
  36.         show = (Button) this.findViewById(R.id.button2);  
  37.   
  38.         // 进入应用使用直接显示上次保存的输入  
  39.         SharedPreferences sharedPreferences = getSharedPreferences(  
  40.                 "chenjianwu", MODE_PRIVATE);  
  41.         parem1.setText(sharedPreferences.getString("name"""));  
  42.         parem2.setText(Integer.toString(sharedPreferences.getInt("age"1)));  
  43.         // 取缓存数据(/data/data/cache)追加显示  
  44.         String appendCache = null;  
  45.         try {  
  46.             appendCache = getCache("cjw");  
  47.         } catch (IOException e) {  
  48.             // TODO Auto-generated catch block  
  49.             e.printStackTrace();  
  50.         }  
  51.         parem1.append("+缓存追加:" + appendCache);  
  52.         // 读取内部存储器数据,追加显示  
  53.         String appendInternal = null;  
  54.         try {  
  55.             appendInternal = getInternal("hello_file");  
  56.         } catch (IOException e) {  
  57.             // TODO Auto-generated catch block  
  58.             e.printStackTrace();  
  59.         }  
  60.         parem1.append("+读取内部存储器追加:"+appendInternal);  
  61.   
  62.     }  
  63. /** 
  64.  * 按钮监听事件,保存数据和显示数据 
  65.  * @param view 
  66.  * @throws IOException 
  67.  */  
  68.     public void listener(View view) throws IOException {  
  69.         Button button = (Button) view;  
  70.         String name = parem1.getText().toString().trim();  
  71.         int age = Integer.parseInt(parem2.getText().toString().trim());  
  72.         SharedPreferences preferences = getSharedPreferences("chenjianwu",  
  73.                 MODE_PRIVATE);  
  74.   
  75.         switch (button.getId()) {  
  76.   
  77.         case R.id.button1:  
  78.             Editor editor = preferences.edit();// 声明编辑器,编辑内容后commit()来提交编辑结果  
  79.             editor.putString("name", name);  
  80.             editor.putInt("age", age);  
  81.             editor.commit();  
  82.             // 使用内部存储器保存文件  
  83.   
  84.             String FILENAME = "hello_file";  
  85.             String string = "hello world 你好!";  
  86.             FileOutputStream fos = openFileOutput(FILENAME,  
  87.                     Context.MODE_PRIVATE);  
  88.             fos.write(string.getBytes());  
  89.             fos.close();  
  90.             // 使用缓存文件保存数据  
  91.             File catchFile = new File(getCacheDir(), "cjw");// getCacheDir()返回cache的绝对路劲  
  92.   
  93.             FileOutputStream catchoutput = new FileOutputStream(catchFile);  
  94.             catchoutput.write(string.getBytes());  
  95.   
  96.             break;  
  97.         case R.id.button2:  
  98.             parem1.setText(preferences.getString("name"""));  
  99.             parem2.setText(Integer.toString(preferences.getInt("age"1)));  
  100.         default:  
  101.             break;  
  102.         }  
  103.   
  104.     }  
  105.   
  106.     /** 
  107.      * 读取缓存文件内容(/data/data/cache) 
  108.      *  
  109.      * @param filename 
  110.      *            文件名 
  111.      * @return 返回Sting类型 
  112.      * @throws IOException 
  113.      */  
  114.     public String getCache(String filename) throws IOException {  
  115.         File f = new File(getCacheDir(), filename);  
  116.         FileInputStream fis = new FileInputStream(f);  
  117.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  118.         byte[] data = new byte[1024];  
  119.         int len = -1;  
  120.         while ((len = fis.read(data)) != -1) {  
  121.             baos.write(data, 0, len);  
  122.         }  
  123.         return new String(baos.toByteArray());  
  124.     }  
  125.   
  126.     /** 
  127.      * 获取内部存储器文件内容(/data/data/files) 
  128.      *  
  129.      * @param filename 
  130.      * @return 
  131.      * @throws IOException 
  132.      */  
  133.     public String getInternal(String filename) throws IOException {  
  134.         FileInputStream fis = openFileInput(filename);//调用openFileInput()来获取内部存储器输入流  
  135.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  136.         byte[] data = new byte[1024];  
  137.         int len = -1;  
  138.         while ((len = fis.read(data)) != -1) {  
  139.             baos.write(data, 0, len);  
  140.         }  
  141.         return new String(baos.toByteArray());  
  142.   
  143.     }  
  144.   
  145.     @Override  
  146.     public boolean onCreateOptionsMenu(Menu menu) {  
  147.         // Inflate the menu; this adds items to the action bar if it is present.  
  148.         getMenuInflater().inflate(R.menu.main, menu);  
  149.         return true;  
  150.     }  
  151.   
  152. }  

布局文件:

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  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.     <TextView  
  12.         android:id="@+id/textView1"  
  13.         android:layout_width="wrap_content"  
  14.         android:layout_height="wrap_content"  
  15.         android:text="参数1:" />  
  16.   
  17.     <TextView  
  18.         android:id="@+id/textView2"  
  19.         android:layout_width="wrap_content"  
  20.         android:layout_height="wrap_content"  
  21.         android:layout_alignLeft="@+id/textView1"  
  22.         android:layout_below="@+id/textView1"  
  23.         android:layout_marginTop="64dp"  
  24.         android:text="参数2:" />  
  25.   
  26.     <EditText  
  27.         android:id="@+id/editText1"  
  28.         android:layout_width="fill_parent"  
  29.         android:layout_height="wrap_content"  
  30.         android:layout_alignTop="@+id/textView2"  
  31.         android:layout_toRightOf="@+id/textView2"  
  32.         android:ems="10" >  
  33.   
  34.         <requestFocus />  
  35.     </EditText>  
  36.   
  37.     <EditText  
  38.         android:id="@+id/editText2"  
  39.         android:layout_width="fill_parent"  
  40.         android:layout_height="wrap_content"  
  41.         android:layout_alignTop="@+id/textView1"  
  42.         android:layout_toRightOf="@+id/textView1"  
  43.         android:ems="10" />  
  44.   
  45.     <Button  
  46.         android:id="@+id/button1"  
  47.         android:layout_width="wrap_content"  
  48.         android:layout_height="wrap_content"  
  49.         android:layout_alignLeft="@+id/textView2"  
  50.         android:layout_below="@+id/editText1"  
  51.         android:layout_marginTop="129dp"  
  52.         android:text="保存"   
  53.         android:onClick="listener"/>  
  54.   
  55.     <Button  
  56.         android:id="@+id/button2"  
  57.         android:layout_width="wrap_content"  
  58.         android:layout_height="wrap_content"  
  59.         android:layout_alignBaseline="@+id/button1"  
  60.         android:layout_alignBottom="@+id/button1"  
  61.         android:layout_alignRight="@+id/editText1"  
  62.         android:text="显示"  
  63.         android:onClick="listener" />  
  64.   
  65. </RelativeLayout>  
0 0