数据存储
文件权限
文件权限标识符:-rwxrw-r–
共10位,分为4段。注:r:可读,w:可写,x:可执行。
第一段(第1位):目录或文件,-表示文件,d表示目录
第二段(第2-4位,共3个字符串):文件所属用户对它的权限
第三段(第5-7位,共3个字符串):文件所属用户组用户对它的权限
第四段(第8-10位,共3个字符串):其他用户对它的权限
8进制表示文件权限规则:r=4,w=2,x=1。
因此,-rwxrw-r–用8进制表示:764
内存存储
应用安装后,系统会根据每个应用的包名创建一个/data/data/包名/的文件夹
File file = new File("/data/data/包名/files/info.txt");
File file = new File(getFilesDir(), "info.txt");
//getFilesDir():/data/data/包名/files/
//getCacheDir():/data/data/包名/cache/
SD卡存储
File file = new File(Environment.getExternalStorageDirectory(),"info.txt");
SharedPrefrerences存储
存储
SharedPreferences sp = this.getSharedPreferences("config", 0); //参数一次为文件名,操作模式
Editor editor = sp.edit();
editor.putString("data", "137****2574");
editor.commit();
获取
SharedPreferences sp = this.getSharedPreferences("config", 0);
String data = sp.getString("data");
问题
SharedPreferences不否支持进程同步
不支持进程同步,基于单个文件,默认是没有考虑同步互斥。而且,APP对SP对象做了缓存,不好互斥同步
MODE_MULTI_PROCESS的作用是什么
在getSharedPreferences的时候, 会强制让SP进行一次读取操作,从而保证数据是最新的. 但是若频繁多进程进行读写 . 若某个进程持有了一个外部sp对象, 那么不能保证数据是最新的. 因为刚刚被别的进程更新了
如何实现SharedPreferences的进程同步
ContentProvider基于Binder,不存在进程间互斥问题,对于同步,也做了很好的封装,不需要开发者额外实现
另外ContentProvider的每次操作都会重新getSP. 保证了sp的一致性
XML文件存储
字符串形式生成
StringBuilder sb = new StringBuilder();
//数据保存到文件
sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); //<xml 头>
sb.append("<student>"); //<student>
sb.append("<name>"); //<name>张三</name>
sb.append(name);
sb.append("</name>");
sb.append("</student>"); //</student>
序列化器生成
// 1.得到xml文件的序列化器
XmlSerializer serializer = Xml.newSerializer();
// 2.指定序列化器的一些初始参数
File file = new File(getFilesDir(), name + ".xml");
FileOutputStream os = new FileOutputStream(file);
serializer.setOutput(os, "utf-8");
// 3.写xml文件.
serializer.startDocument("utf-8", true); //写开头
serializer.startTag(null, "student"); //开始标签
serializer.startTag(null, "name");
serializer.text(name); //文本标签
serializer.endTag(null, "name"); //结束标签
serializer.endTag(null, "student");
serializer.endDocument(); //写结尾
os.close();
XML文件解析
DOM解析
是一种基于对象的API,它会将XML文件的所有内容以文档树方式存放在内存中,然后允许使用DOM API遍历XML树、检索所需的数据,这样便能根据树的结构以节点形式来对文件进行操作。
由于DOM需要将整个XML文件以文档树的形式存放在内存中,消耗内存比较大,在Android下不介意使用该种方式进行解析。
SAX解析
会逐行扫描XML文档,当遇到标签时触发解析处理器,采用事件处理的方式解析XML。它在读取文档的同时即可对XML进行处理,不必等到文档加载结束,相对快捷,而且也不需要将整个文档加载进内存,因此不存在占用内存的问题,可以解析超大XML。但是,SAX解析只能用来读取XML的数据,无法进行增删改。
PULL解析
跟SAX解析类似,也是基于事件处理的方式。PULL解析器是一个开源的Java项目,既可以用于Android应用,也可以用与JavaEE程序。Android已经集成了PULL解析器,因此,在android中最常用的解析方式就是PULL解析。
SAX和PULL解析对比
Pull 解析器的运行方式与SAX 解析器相似,都属于事件驱动模式。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用一个switch 对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text 类型元素的值。
SAX 解析器的工作方式是自动将事件推入事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull 解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。
pull解析
//1.获取到一个xml解析器
XmlPullParser parser = Xml.newPullParser();
//2.设置解析器的初始化参数
FileInputStream inputStream = new FileInputStream(file);
parser.setInput(inputStream, "utf-8");
//3.解析xml文件
int type = parser.getEventType(); //得到第一个事件的类型.
//当事件类型不是文档的结尾则一直遍历每一个节点
while(type!=XmlPullParser.END_DOCUMENT){
if(type==XmlPullParser.START_TAG){
//开始节点
//判断节点的名称
if("name".equals(parser.getName())){
String nameStr = parser.nextText();
}
}
type = parser.next();//获取下一个事件类型
}
inputStream.close();//浪费资源 造成内存泄漏!
} catch (Exception e) {
e.printStackTrace();
}
Sqlite数据库
//数据库创建
public class MyDataBaseOpenHelper extends SQLiteOpenHelper {
public MyDataBaseOpenHelper(Context context) {
super(context, "test.db", null, 2);
}
@Override
public void onCreate(SQLiteDatabase db) {
System.out.println("数据库 oncreate");
db.execSQL("create table student (_id integer primary key autoincrement, name varchar(20), phone varchar(30))");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
System.out.println("数据库要被更新了,onupgrade");
// db.execSQL("alter table student add account varchar(20)");
}
}
//增
ContentValues values = new ContentValues();
values.put(columnName, value);
db.insert(tableName,null,values); //第一个参数表名; 第二个参数:如果ContentValues 为空,那么默认情况下是不允许插入空值的,但是如果给该参数设置了一个指定的列名,那么就允许ContentValues 为空,同时给该列插入null 值。第三个参数:要插入的数据
//删
//第一个参数:表名;第二个参数:删除条件;第三个参数:用于替换第二个参数的?; 返回值:删除成功的个数
db.delete(tableName, "name=?", new String[]{value});
//改
ContentValues values = new ContentValues();
values.put(columnName, value
db.update(tableName, values, "name=?", new String[] { value });
//查
Cursor cursor = db.query(tableName, 需要查询的列, "name=?", new String[]{value},null,null, 排序);
两种SQLiteDatabase的不同
1.getWritableDatabase()
该方法返回的对象和另外一个方法返回的对象没有任何差异,返回的对象对数据库都可以进行读、写操作,当磁盘已满或者权限不足的情况下该方法会抛出异常。
2.getReadableDatabase()
跟另外一个方法相比,在磁盘已满的情况下,该方法不会抛出异常,而是返回一个只读的数据库操作对象。根据这两种方法返回对象的差异,如果需要对数据库进行查询操作则推荐使用后者,如果添加、修改、删除数据则推荐使用前者。
数据库的升级
构造方法中传递一个int类型,比之前大的值
数据库的事物
//事物保证执行的数据库操作能完整执行,否则全部不执行
BankDBOpenHelper helper = new BankDBOpenHelper(this);
SQLiteDatabase db = helper.getWritableDatabase();
db.beginTransaction(); // 开启事务
try {
// 模拟转账的操作,
db.execSQL("update account set money=money-100 where name='zhangsan'");
db.execSQL("update account set money=money+100 where name='lisi'");
db.setTransactionSuccessful(); // 设置事务执行成功
} finally {
db.endTransaction();//还可以回滚代码
}
db.close();
Sqlite3工具的使用
sqlite3 是Android 内置的操作数据库工具,使用该工具可以直接对SQLite 数据库进行操作
1、在命令行界面使用adb shell 命令进入linux 内核
2、使用cd 命令进入数据库所在目录(数据库的路径为”/data/data/应用包名/databases/数据库”)
3、使用”sqlite3 数据库名”进入数据库操作模式
JSON
概述
纯文本,具有自我描述性,人类可读;可通过JavaScript解析;可使用AJAX传输
与XML的不同
更短,读写速度更快;无结束标签;可使用数组,能使用内建的JavaScript eval()方法解析;不使用保留字
解析
1 解析json对象
JSONObject jsonObject = new JSONObject(json);
//解析字符串
String name = jsonObject.getString("name"); //两个方法效果一样
String name = jsonObject.optString("name");
//解析数组
JSONArray name = jsonObject.getJSONArray("name");
//解析
JSONObject name = jsonObject.getJSONObject("name");
2 解析json数组
JSONArray jsonArray = new JSONArray(json);
Gson解析
1 添加依赖
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.0'
2 解析Gson对象
Gson gson = new Gson();
MyBean bean = gson.fromJson(json, MyBean.class); //生成bean对象
3 解析Gson数组
Gson gson = new Gson();
List<MyBean> bean = gson.fromJson(json, new TypeToken<List<MyBean>>() {}.getType()); //生成泛型为MyBean的List集合
Fastjson 解析
1 添加依赖
compile 'com.alibaba:fastjson:1.1.55.android'
2 解析json对象
MyBean bean = JSON.parseObject(json, MyBean.class);
3 解析json数组
List<MyBean> bean = JSON.parseArray(json, MyBean.class);