android数据保存的三种方式
- 使用SharedPreferences存储简单的键值对数据
- 使用android的文件系统保存数据
- 使用SQite数据库存储
文件存储是什么
安卓的文件存储分为内部存储和外部存储。以前的手机内存比较少,可以扩展SD卡,sd卡即外部存储。现在大部分手机都已经不再使用SD卡,内存也不小,好一点的手机都能达到16G。内部存储的数据只能由该应用程序访问,可以防止其他恶意程序访问,比较安全,但是一旦应用被删除,程序数据都会被删除。外部存储容量大,可读可写范围大,任何应用程序和用户(android支持多用户)都可以读写,这些文件的安全性和可靠性得不到保障。重要的数据保存在内部存储中,不重要的大的数据保存在外部存储中,比如用户下载的电影,音乐,图片等。任何设备都会有内部存储,但不一定会有外置sd卡,4.0以上的设备还支持usb存储,当手机连接usb时,能读写usb中的内容
android 支持java I/O操作主要使用FileiInputStream 和FileOutpuStream 这两个类来实现文件的存储与读取。获取这两个对象有两种方法,一是使用标准的java I/O操作,二是使用Android Context类中的openFileInput() 和openFileOutput()方法。
使用内部存储
保存数据到内部存储中
Context类提供了一个openFileOutput()方法,讲数据存储到指定的文件中,返回一个FileOutputStream对象,获得FileOutputStream就可以使用java流的方式写入文件。方法如下
@Override
public FileOutputStream openFileOutput(String name, int mode)
throws FileNotFoundException {
return mBase.openFileOutput(name, mode);
}
使用这个方法默认将文件存储到/data/data/package-name/files/目录下,第一个参数是保存的文件名,这个文件名不能包好任何路径。第二个参数是文件的操作模式,有MODE_PRIVATE 和MODE_APPEND两种模式,MODE_PRIVATE是默认的操作模式,如果已经存在这个文件,这回覆盖原文件中的内容。MODE_APPEND会在原文件末尾添加新的内容,如果文件不存在则创建新文件。
下面的代码展示如何将一段文本内容保存到文件中,使用MODE_APPEND模式。
String fileName = "myfile";
String string = "hello ,I have been saved"
FileOutputStream fout ;
try{
fout = openFileOutput(fileName,Context.MODE_APPEND);
fout.write(string.getBytes() )
fout.close();
}catch (Exeception e){
e.printStackTrace();
}
下面使用File API来实现上面的功能,使用Context.getFileDir获得程序默认内存存储的路径,将构造器FileOutputStream(File file,boolean apped)中的append设为true,表示如果文件已经存在,在在文件末尾添加新的文件内从,false 则表示覆盖原有文件的内容,
String fileName = "myFile";
String string = "hello , I have been saved!";
File file = new File(getFileDiir(),fileName);
FileOutputStrea fout = null;
BufferedWriter writer = null;
try{
fout = new FileOutputStream(file,true);
writer = new BufferdWriter(new OutputStreamWriter(fout));
writer.write(string);
}catch(Exception e){
e.printStackTrace();
}
finally{
if(writer != null){
try{
write.close();
}catch(IOException e){
e.printStackTrace();
}
}
if (fout != null){
try{
fout.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
如果需要缓存文件,使用getCacheDir(),可以获得当前应用的默认缓存路径,该路径为/data/data/package-name/cache/。该方法为抽象方法. 再调用createTempFile(),方法源代码如下。该方法返回一个File对象,第一参数为缓存文件的前缀,第二个参数为缓存文件的后缀,第三个参数为File。这个方法会在给定的路径下创建一个空的幻刺文件。如果第一个参数为mytempfile,第二个参数为.txt,第三个参数为getCaheDir(),则会在,/data/data/package-name/cache/下创建一个mytempfile*.txt的文件,*为任意数量字符。
public static File createTempFile(String prefix, String suffix, File directory)
throws IOException {
// Force a prefix null check first
if (prefix.length() < 3) {
throw new IllegalArgumentException("prefix must be at least 3 characters");
}
if (suffix == null) {
suffix = ".tmp";
}
File tmpDirFile = directory;
if (tmpDirFile == null) {
String tmpDir = System.getProperty("java.io.tmpdir", ".");
tmpDirFile = new File(tmpDir);
}
File result;
do {
result = new File(tmpDirFile, prefix + Math.randomIntInternal() + suffix);
} while (!result.createNewFile());
return result;
}
下面代码展示如何将一段文本内容缓存到文件中
File file = null;
FileOutputStream fout = null;
String string = "hello,I have been saved";
BufferedWriter writer = null;
try {
file = File.createTempFile("mytempfile",".txt",getCacheDir());
fout = new FileOutputStream(file,true);
writer = new BufferedWriter(new OutputStreamWriter(fout));
writer.write(string);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (writer != null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fout != null){
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
从内部存储中读取数据
类似将数据保存到文件中,Context类提供了一个openFileInput()方法,用于从文件中读取数据。它只接受一个参数,即它要读取的文件名,系统会自动去/data/data/pacakge-name/files/目录下加载这个文件,并返回一个FileInputStream对象,然后可以java I/O的操作来读取文件。
下面代码展示如何从文件中读取文本数据
FileInputStream fin= null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder();
try{
in = openFileIntput("myfile");
reader = new BufferedReader(new InputStreamReader(in) );
String line = "";
while(line = reader.readline() != null){
conten.append(line);
}
}catch(IOException e){
e.printStackTrace();
}finally{
if (reader != null){
try{
reader.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(fout != null){
try{
fout.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
使用外部存储
权限声明
使用外部存储时,最好声明读写外部存储的权限。目前所有应有都有读外部存储的权限,不必额外声明权限。日后可能会有改变。在AndroidManifest.xml中添加如下代码
<manifest ...>
<user-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<user-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
</manifest>
检查外部存储是否可用
有些设备可能没有外部存储,在使用外部存储时,先检查外部存储是否可用,使用getExternalStorageState(),该方法返回一个String ,如果返回的String 为MEDIA_MOUnTED,然后就可以在外部存储上进行文件读写。下面的方法可以用来判断外部存储是否可用(该方法来自android 文档)
/**
*检查是否可以向外部存储写入数据
*@return ture如果可以向外部存储写入数据,否则返回false。
*/
public boolean isExternalStorageWriteable(){
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state)){
return true;
}
return false;
}
/**
*检查是否可以读取外部存数据
*@return ture 如果可以读取外部存储数据,否则返回false
*/
public boolean isExternalStorageReadable(){
String sate = Environment.getEXternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){
return ture;}
return false;
}
选择存储文件的类型
虽然外部存储的文件可以被其他用户和应用程序读写,但还是将文件保存为公共的文件或者时私有的文件
公共文件(Public files)可以被其他应用自由读写的文件,当用户把你的程序卸载后,这些文件仍然保留在系统上吗可以被用户使用,比如下载的音乐和视频
私有文件(Private files),私有文件属于你的自己程序,这些文件不对其他应用提供数据。当用户卸载程序时,这些数据也应该被删除。
使用公共文件(Public files)
使用公共文件需要获取公共文件的存储路径,使用getExternalStoragePublicDirectory(),接受一个String 参数,代表要保存的文件的类型。参数如
DIRECTORY_MUSIC
DIRECTORY_PODCASTS
DIRECTORY_RINGTONES
DIRECTORY_ALARMS
DIRECTORY_NOTIFICATIONS
DIRECTORY_PICTURES
DIRECTORY_MOVIES
DIRECTORY_DOWNLOADS
DIRECTORY_DCIM
DIRECTORY_DOCUMENTS
系统会将文件保存到合适的公共目录下,即使用户卸载了程序,数据仍然会被保留。
使用私有文件
使用getExternalFileDir(),获取私有文件路径,改方法接受一个String 参数,参数表示文件类型,和上面类似。如果传递一个null,返回程序在外部存储上的默认路径。即 /sdcard/|Android/data/package-name/files/目录。如果用户卸载你的程序,这个目录会被系统自动删除。
文件存储实例
下面用一个实例来演示文件存储。程序主界面如下,一个文本输入框,用来获取用户输入内容,一个保存按钮保存用户输入的内容,ActionBar上有一个CheckBox,提示用户使用内部存储还是使用外部存储。默认保存在内部存储中。如果用勾选使用外部存储,用户输入的内容会保存到外部存储中,因为是私有的文件内容,使用外部存储时,使用private files。点击下载源码