今天和大家聊聊Android数据存储的那些事,顺便对这一块知识做一个总结归纳。学习Android开发,知识很多很杂,对于一个刚学习的人来说,学的即使再多但在实际的开发中却也不懂得怎么去用,碰到问题了也不知道选择哪种方式去解决,有时候碰到一个问题咋一看感觉很复杂,不知道如何去下手;有时候一个问题好像又有很多种解决办法,不知道选择哪一种比较好;学的知识综合运用到一个完整的项目中问题百出,各种卡住无法往下写,可是对于一个单独的知识点似乎又懂点。所有的这些问题对于一个新入门的人来说都会有所体会,其根本的原因是我们对自己所学的知识不是很深入,不熟练,更谈不上对它们的整体认识,今后的博客我会把一些知识归类总结,供大家学习借鉴,欢迎补充指正~~
进入正题,Android对数据的保存可以分为临时保存和永久保存,临时保存主要保存在一些寄存器、内存中,比如我们创建的一些变量、数组、集合等,永久的保存就是把数据写入到一个文件中,然后保存文件。Android是基于Linux的,而Linux把一切都看做文件来处理,所以今天就来看Android是如何用文件来处理数据的。其主要有5中形式:
1.SharedPreferences
2.普通文件保存
3.数据库保存(Sqlite)
4.网络保存
5.ContentProvider
一、SharedPreferences形式,将文件用XML的形式保存在:/data/data/包名/shared_prefs 下面。
其中Activity为了简化存储,提供了一个独有的方法getPreferences(int mode),此方法与Context的getSharedPreferences(String name,int mode),用法一样,唯一不同点在于其不能指定保存文件名字,其保存名为: 包名.类名,所以一个Activity只能保存一个这样的文件,并且每个Activity类都可以保存一个这样的文件。
mode的形式有一下几种:
Context.Mode_APPEND:如果文件存在就在当前文件后面添加,不存在就创建
Context.Mode_PRIVATE:私用模式,文件存在就在后面添加(不会覆盖原来的内容,亲测),不存在就创建
Context.MODE_MULTI_PROCESS:多线程操作时用到,现在已经弃用
Context.MODE_WORLD_READABLE:用这种模式保存的数据其他应用也能访问,并且可以读写
Context.MODE_WORLD_READABLE:同上,不过其他应用只能读
注意:如果保存为中文文件名,无法从模拟器里导入到电脑
Preferences形式:
Editor editor = getPreferences(Context.MODE_PRIVATE).edit();
editor.putBoolean("boolean", false).putString("string", "字符串");
editor.commit();
<strong><span style="font-size:24px;">结果:</span></strong>
<img src="https://img-blog.csdn.net/20151102114734899?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
SharedPreferences形式:Editor ed = getSharedPreferences("hobby", Context.MODE_APPEND).edit();
ed.putBoolean("喜欢加班吗?", false).putString("喜欢吃水果吗?", "喜欢");
ed.commit();
<strong><span style="font-size:24px;">结果:</span></strong>
<img src="https://img-blog.csdn.net/20151102114816091?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
<strong><span style="font-size:24px;">存储结构:</span></strong>
<img src="https://img-blog.csdn.net/20151102114855070?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
读取的方法:getSharedPreferences().getBoolean(String key,boolean default);前一个为对应的key,后一个为key不存在给的默认值
使用思路:(类似于数据库的操作方式,事物方式):先调用getPreference()获取getSharedPreferences(),传入对应的参数,然后得到Editor对象,调用put方法,commit()方法提交。二、普通文件保存
文件保存主要涉及到的类有:File、FileInputStream、FileOutputStream、RandomAccessFile
1.File类
代表一个文件抽象对象,可以是一个文件夹,也可以是一个具体的文件
以上为构造方法,第一个直接传入路径,第二个传一个URI对象,后面两个都是前一个传文件夹路径,后面穿文件的名字,不同的是前一个用File对象表示文件夹路径,后一个用字符串表示文件夹路径。
2.FileInputStream类、FileOutputStream类
FileInputStream代表一个文件输入流,从文件读取数据
// 从文件读取数据
public static InputStream ReaderFile(String path, String fileName) {
InputStream is = null;
if (fileName == null || fileName.equals("")) {
return null;
}
File file = new File(((path.startsWith("/") ? "" : File.separator)) + path
+ (path.endsWith("/") ? "" : File.separator) + fileName);
if (!file.exists())
return null;
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return is;
}
FileOutputStream代表文件输出流,把数据保存到文件中
// 保存数据到文件
public static void saveData(String path, String fileName, byte[] data) {
// 处理传入的路径,拼接成一个新的路径
String dpath = (path == null ? File.separator : path.startsWith("/") ? "" : File.separator)
+ (path.endsWith("/") ? path : path + File.separator);
// 创建文件对象
File fd = new File(dpath);
if (fileName == null || data == null) {
Log.d(TAG, "参数错误");
return;
} else if (!fd.isDirectory()) {
Log.d(TAG, "非法的路径");
return;
} else {
if (!fd.exists())
// 不存在就创建绝对路径
fd.mkdirs();
// 创建需要保存的文件对象
File file = new File(dpath + fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
fos.write(data);
fos.flush();
Log.d(TAG, "保存成功!");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
// 关流
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3.
RandomAccessFile类,随机文件读写类,常用来处理文本文件
常用方法:
seek(long offset):移动文件指针到指定的位置,offset是相对于文件开头的位置,单位为字节,如果移动到文件中间然后进行写操作,会覆盖掉后面的数据
skipBytes(int count):跳过count个字节,相对当前位置,单位为字节
示例:
RandomAccessFile raf = new RandomAccessFile("/storage/sdcard0/fruit.tex", "rw");
// 存数据
raf.write("猕猴桃".getBytes());
raf.writeInt(8);
raf.writeChars("提子");
raf.writeLong(10);
// 取数据
raf.seek(0);
byte[] buf = new byte[9];
int len = raf.read(buf);
String wiki=null;
if (len != -1) {
wiki = new String(buf);
}
int wiki_price=raf.readInt();
char c1=raf.readChar();
char c2=raf.readChar();
String grape=new String(new char[]{c1,c2});
long grape_price=raf.readLong();
//打印读取到的数据
Log.e(TAG,wiki+":"+wiki_price+","+grape+":"+grape_price);
扫描关注我的微信公众号:
限于篇幅的原因,后面的文章请点击:Android数据存储总结之二