您的位置:首页 > 移动开发 > Android开发

Android4开发 之:数据存储

2015-01-04 10:18 435 查看


数据存储基本知识


Android系统提供了多种数据存储的方式,如下:

1:Shared Preferences:用来存储私有的、原始类型的、简单的数据,通常是Key-value对

2:Internal Storage:在设备内部存储器中存储数据

3:External Storage:在设备的扩展存储上保存数据,通常是SD卡

4:SQLite Databases:SQLite数据库

5:Network Connection:存储数据到网络服务器上


使用Shared Preferences

Shared Preferences是用来存储一些应用私有的、原始类型的、简单的数据的一个框架,保存的数据通常是Key-value对


要获得SharedPreferences对象,通常有两种方法:

1:getSharedPreferences():如果你想要使用多个preferences文件的话,可以通过传入一个识别的名称就可以获取到相应的SharedPreferences对象

2:getPreferences():如果一个preferences文件仅仅在当前的Activity中使用的话,你可以使用这个方法,无需要提供识别的名称。

使用SharedPreferences对象来获取数据非常简单,直接使用相应的getter方法即可


使用SharedPreferences对象来存储数据,大致有如下几步

1:调用edit()方法来得到SharedPreferences.Editor

2:调用相应的put方法值添加进去

3:调用commit来提交保存这些数据


向SharedPreferences对象写入数据

java代码:

查看复制到剪贴板打印

SharedPreferences sp =getSharedPreferences("SP",Activity.MODE_PRIVATE);  

SharedPreferences.Editor editor = sp.edit();  

editor.putString("param1", "sp1");  

editor.putInt("param2", 222);  

editor.commit();  

注意:所有的写入操作应该在一个Editor里面,也就是不要调用多次sp.edit()方法,每调用一次就会创建一个Editor


在获得SharedPreferences对象的时候,需要指定文件创建的模式:

1:MODE_PRIVATE:默认模式,文件只可以被调用该方法的应用程序访问

2:MODE_WORLD_READABLE:赋予所有的应用程序都可以读取该文件

3:MODE_WORLD_WRITEABLE:赋予所有的应用程序都可以写该文件

4:MODE_MULTI_PROCESS:SharedPreference的装载标记,设置它,文件将会在SharedPreference实例被装载到进程的时候检查是否被修改,主要用在一个应用有多个进程的情况。

Android同一个应用不同进程之间,用SharedPreferences方式存储值。这种方式不能及时传递数据,只有系统再一次重启的时候,数据才会一致。

问题所在:

SharedPreferences存储方式有四个模式,2.3以上版本默认MODE_PRIVATE模式。这种模式在一个应用只有一个进程的情形下不会有问题,但若有两个不同的进程,且这两个进程想要公用sharedPreferences,就存在数据一致性问题。

解决方案:

要想解决数据一致性问题,可以将SharedPrefernces设置为MODE_MULTI_PROCESS模式。Android 2.3以前的版本,MODE_MULTI_PROCESS是默认开启的,之后版本需要显示开启。

安全问题:
MODE_PRIVATE (0)安全。
MODE_WORLD_READABLE (1) 不安全。
MODE_WORLD_WRITEABLE (2)不安全。
MODE_MULTI_PROCESS(4)看与谁搭配
若MODE_PRIVATE|MODE_MULTI_PROCESS (4)(也等于MODE_MULTI_PROCESS) 安全;
若MODE_WORLD_READABLE|MODE_MULTI_PROCESS(5) 不安全;
若MODE_WORLD_WRITEABLE|MODE_MULTI_PROCESS(6) 不安全。

MODE_MULTI_PROCESS官方解释:

SharedPreference loading flag: when set, the file on disk will be checked for modification even if the shared preferences instance is already loaded in this process.

注意:

sharePreferenced中数据没有绝对的安全。对于root的手机,都是不安全的。

且不同的APK可以享用同一个进程。数据也可以相互通。

You can also set android:process so that components of different applications run in the same process—provided that the applications share the same Linux user ID and are signed with the same certificates.


从SharedPreferences对象读取数据

java代码:

查看复制到剪贴板打印

SharedPreferences sp = T2.this.getSharedPreferences("SP",Activity.MODE_PRIVATE);  

String p1 = sp.getString("param1","");  

int p2 = sp.getInt("param2",0);  

SharedPreferences的数据以xml存储在data/data/包名/shared_prefs下面


Internal Storage

当应用程序被安装到系统中后,其所在的包会有一个文件夹用于存放自己的数据,只有这个应用程序才有对这个文件夹的写入权限,这个私有的文件夹位于Android系统的/data/data/<应用程序包名>目录下,其他的应用程序都无法向这个文件夹中写入数据。
要读取应用自己的私有文件,就不能直接使用Java I/O的API了,需要使用Activity提供的方法:openFileInput或openFileOutput。


在使用openFileOutput方法的时候,需要指定打开的模式:

1:MODE_PRIVATE:默认模式,文件只可以被调用该方法的应用程序访问
2:MODE_APPEND:如果文件已存在就向该文件的末尾继续写入数据,而不是覆盖原来的数据。
3:MODE_WORLD_READABLE:赋予所有的应用程序对该文件读的权限。
4:MODE_WORLD_WRITEABLE:赋予所有的应用程序对该文件写的权限。


向应用对应的Internal Storage里面写入数据,这里以写对象来示例,如下:

java代码:

查看复制到剪贴板打印

FileOutputStream fout = null;  

ObjectOutputStream os = null;  

try{  

fout = HelloWorldActivity.this.openFileOutput("MyData.txt",Activity.MODE_PRIVATE);  

os = new ObjectOutputStream(fout);  

os.writeObject(list);  

}catch(Exception err){err.printStackTrace();}  

finally{  

try {fout.close();}catch(IOException e1){e1.printStackTrace();}  

try {os.close();} catch(IOException e){e.printStackTrace();}  

}  

不支持BufferedOutputStream  


读取应用对应的Internal Storage里面的数据,这里以读取对象来示例,如下:

java代码:

查看复制到剪贴板打印

FileInputStream fin = null;  

ObjectInputStream os = null;  

try{  

fin = HelloWorldActivity.this.openFileInput("MyData.txt");  

os = new ObjectInputStream(fin);  

Toast.makeText(HelloWorldActivity.this, "read file="+os.readObject(), Toast.LENGTH_LONG).show();  

}catch(Exception err){  

err.printStackTrace();  

}finally{  

try{fin.close();}catch(IOException e1){e1.printStackTrace();}  

try{os.close();}catch(IOException e){e.printStackTrace();}  

}  

同样不支持BufferedInputStream  


Internal Storage-保存Cache文件

如果你希望保存一些Cache数据,你可以使用getCacheDir() 来打开文件,将会把数据存储到一个临时的Cache文件里面。
当设备的内部存储空间低的时候,Android系统可能会清除这些Cache文件,以回收存储空间,这也意味着,你不能在Cache文件里面存储需要持久化的数据。


Internal Storage-其它常用方法


在Context中其他常用的方法:

1:getFilesDir()
得到内部存储的文件系统的绝对路径
2:getDir()
在内部存储中创建目录,如果存在的话就打开这个目录
3:deleteFile()
删除文件
4:fileList()
返回当前应用存储的文件列表


External Storage(操作SD卡)


Android的I/O基本上和Java的I/O是一样的,只有一点点不同的地方,比如:

1:需要加入sdcard的操作权限
2:需要判断sd卡是否存在,存在才能操作
3:放在sdcard的文件是公共的,而放到自己应用目录里面的文件才是私有的


常用的功能

1:在AndroidManifest.xml添加sdcard读写操作权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
</uses-permission>
2:在AndroidManifest.xml添加能创建和删除sdcard文件的操作权限
<uses-permission android:name= "android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
3:判断SD卡是否插入
Environment.getExternalStorageState().equals(android.os.Enviroment.MEDIA_MOUNTED)
4:获得SD卡根目录
Android7及以下版本,使用:Environment.getExternalStorageDirectory()可以获得如下路径“/Android/data/<package_name>/files/”
Android8及以上版本,建议使用:Context的getExternalFilesDir(type)方法,type表示你想要访问什么样的子目录,比如Environment.DIRECTORY_MUSIC,如果访问根目录,就传入null。


从SD卡上读文件,基本就是Java里面I/O的操作,这里以读对象为例:

java代码:

查看复制到剪贴板打印

public Object readFile(String filePathName) {  

Object ret = null;  

FileInputStream fins = null;  

ObjectInputStream os = null;  

try {  

File file = new File(Environment.getExternalStorageDirectory() + filePathName);  

fins = new FileInputStream(file);  

os = new ObjectInputStream(fins);  

ret = os.readObject();  

} catch(Exception err){err.printStackTrace();}finally{  

try {fins.close();}catch(IOException e){e.printStackTrace();}  

try {os.close();}catch(IOException e){e.printStackTrace();}  

}  

return ret;  

}  

比较遗憾的是,目前加上BufferedInputStream就出错  


向SD卡上写文件,基本就是Java里面I/O的操作,这里以写对象为例:

java代码:

查看复制到剪贴板打印

public void writefile(String filePathName,Object obj){  

FileOutputStream fouts = null;  

ObjectOutputStream os = null;  

try {  

File file = new File(Environment.getExternalStorageDirectory() +filePathName);  

if(file.getParentFile().isDirectory() && !file.getParentFile().exists()){  

file.getParentFile().mkdirs();  

}  

if(!file.exists()){ file.createNewFile(); }  

fouts = new FileOutputStream(file);  

os = new ObjectOutputStream(fouts);  

os.writeObject(obj);  

} catch (Exception err) {err.printStackTrace();  

}finally{  

try {fouts.close();}catch(IOException e){e.printStackTrace();}  

try {os.close();}catch(IOException e){e.printStackTrace();}  

}  

}  

如果要保存成Cache文件,可以使用Context的getExternalCacheDir方法  

   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐