Android中的数据存储之文件存储、SharedPreferences和Pull解析
一、数据存储的五种方式
- 文件存储
- 分手机内部存储、手机外部存储
- 以IO流形式存放,可存放较大数据
- SharedPreferences
- 本质是一个XML
- 以Map形式存放简单的配置参数
- SQLite
- 轻量级、跨平台数据库
- 所有数据都是存放在手机上的单一文件内,占用内存小
- ContentProvider
- 将本应用的私有数据提供给其他应用使用
- 网络存储
- 数据存储都服务器上
二、文件存储(IO)
1. 手机内部存储
1.1 概述
存储位置:/data/data//文件夹下
特点
- 存放应用私有的小数据
- 卸载应用时会同步删除
1.2 API之Context
获取上下文对象
- this //当前Activity的上下文对象
- this.getApplicationContext() //整个应用的上下文对象
获取文件夹
- context.getFilesDir(); //获取到data/data//files
- context.getCacheDir();//获取到data/data//cache,当清理缓存时会被清理
获取流
- context.openFileOutput(name,mode);//获取文件输出流;文件名,读写模式设置权限;也是保存到data/data//files
- context.openFileInput(name);//读取文件
文件权限
- MODE_PRIVATE //只有当前应用可读写
- MODE_WORLD_WRITABLE+MODE_WORLD_READABLE //全局可读又可写
- …
2. 手机外部存储
2.1 概述
- 存储位置: /mnt/sdcard,这个路径会因版本不同而不同
- 特点:
- 应用卸载后文件不会被删除
- 存放大文件
2.2 API之Environment
常量
- MEDIA_MOUNTED //已挂载
- MEDIA_UNMOUNTED //未挂载
- MEDIA_SHARED //未挂载,作为USB大内存设备供电脑使用
- …
成员变量
- DIRECTORY_MUSIC //存储音频文件的标准目录
- DIRECTORY_DOWNLOADS //存放下载的文件
- …
方法
- getExternalStorageState(); //获取外存状态(挂载/未挂载/…)
- getExternalStorageDirectory(); //获取外存根目录,因平台版本不同而不同
- getExternalStoragePublicDirectory(String type); //获取顶级公共目录用于存放特定类型的文件
- getRootDirectory(); //获取Android的根目录
- isExternalStorageRemovable(); //判断外存是否可移除;true就是SD卡,false就是内置的外存
2.3 权限说明
com.permission.WRITE_EXTERNAL_STORAGE
com.permission.READ_EXTERNAL_STORAGE
三、SharedPreferences存储
1. 概述
- 存储位置:/data/data//shared_prefs/
- 键值对形式保存在xml文件中
- 用途:保存配置参数(基本数据类型和String)
2. API
- 获取SharedPreferences
this.getSharedPreferences(name,mode);
//通过上下文对象获取共享引用参数
//因为在包中的文件是由上下文对象管理的
//name为文件名(不需要带后缀),mode设置访问权限
//常见权限
Context.MODE_PRIVATE//私有
Context.MODE_APPEND//拼接
- 编辑SharedPreferences
- 通过SharedPreferences.Editor编辑,有put方法和commit方法
- 通过SharedPreferences的get方法获取
//获取SharedPreferences
SharedPreferences sf = context.getSharedPreferences("info",
Context.MODE_PRIVATE);
//获取SharedPreferences编辑器
Editor editor = sf.edit();
//放入map值
editor.putString("userName", usr.getUserName());
editor.putString("password", usr.getPassword());
//提交修改
editor.commit();
//获取map值,第二个参数为获取不到时的默认值
String userName = sf.getString("userName", "");
String password = sf.getString("password", "");
生成的xml文件
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="userName">admin</string>
<string name="password">123</string>
</map>
四、XML存储与解析
1. XML序列化
1.1 概念
序列化:将对象状态转换成可保存或传输的过程。将IO流中的对象变得像基本数据类型一样易于传输,实际上就是把javabean的属性通过结构化的文件(比如xml、json)表示。
1.2 将javabean序列化成xml
过程:构造XML序列化器,通过序列化器构建一个输出流,再通过startDocument设置文档头,通过startTag设置开始标签,通过attribute设置属性,最后通过endTag结束标签,通过endDocument结束文档输出。
User user = new User("1220", "admin", "123");
XmlSerializer serializer = Xml.newSerializer();
OutputStream os = new FileOutputStream(new File(this.getFilesDir(),
"user.xml"));
serializer.setOutput(os, "UTF-8");
serializer.startDocument("utf-8", true);
serializer.startTag(null, "user");
serializer.startTag(null, "id");
serializer.text(user.getId());
serializer.endTag(null, "id");
serializer.startTag(null, "userName");
serializer.text(user.getUserName());
serializer.endTag(null, "userName");
serializer.startTag(null, "password");
serializer.text(user.getPassword());
serializer.endTag(null, "password");
serializer.endTag(null, "user");
serializer.endDocument();
os.close();
2. XML解析
2.1 几种解析XML的方式
dom解析
- 先加载dom树到内存到再解析,占用内存大
- 适合小文件的解析
- 可以修改xml中的数据
sax解析
- 边读边解析,占用内存小
- 事件处理机制
- 只能读取,不可修改xml中的数据
- 适合大文件的解析
- 解析器产生的事件是一个方法
pull解析
- 开源项目,在Android SDK中集成了
- 边读边解析,占用内存小
- 事件处理机制
- 只能读取,不可修改xml中的数据
- 解析器产生的事件是一个数字
2.2 解析XML成JavaBean
过程:首先构建一个pull解析器,通过类加载器获取一个xml文件输入流,并传入pull解析器;解析器读取输入流中的信息,我们根据事件类型获取关心的数据并设置到javabean中,直到文档结束。
事件类型:
- START_DOCUMENT//文档开始
- START_TAG//开始标签
- TEXT//标签体
- END_TAG//结束标签
- END_DOCUMENT//文档结束
XmlPullParser parser = Xml.newPullParser();
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream("bookstore.xml");
ArrayList<Book> books = null;
Book book = null;
int eventType = parser.getEventType();
parser.setInput(in, "utf-8");
while (eventType != XmlPullParser.END_DOCUMENT) {
String tagName = parser.getName();
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
books = new ArrayList<Book>();
break;
case XmlPullParser.START_TAG:
if (tagName.equals("book")) {
book = new Book();
String id = parser.getAttributeValue(0);
book.setId(id);
} else if (tagName.equals("name")) {
String name = parser.nextText();
book.setName(name);
} else if (tagName.equals("price")) {
String price = parser.nextText();
book.setPrice(price);
} else if (tagName.equals("author")) {
String author = parser.nextText();
book.setAuthor(author);
}
break;
case XmlPullParser.END_TAG:
if (tagName.equals("book")) {
books.add(book);
book = null;
}
break;
}
eventType = parser.next();
}