数据存储
数据存储
Android中的数据存储有5种
- 文件存储
- SharedPreferences
- SQLite数据库
- ContentProvider
数据存储方式
- 文件存储:Android提供了
openFileInput()和openFileOutput()方法来读取设备上的文件,其读取方式与Java中 I/O 程序时一样的。 - SharedPreferences:这是Android提供的用来存储一些 “简单的配置信息的一种机制”,它采用了XML的格式将数据存储到设备中。
- SQLite数据库:SQLite是数据库 “自带的一个 轻量级的数据库”,(它运算速度快,占用资源少,还支持SQL语法),一般使用它作为复杂数据的存储引擎。
- ContentProvider:Android的四大组件之一,主要用于 “应用程序之间的数据切换”,可以将自己的数据共享给其它应用程序使用。
- 网络存储:将数据库存储到 “服务器上”,通过网络提供的存储空间来存储/获取信息。
1.文件存储
文件存储是Android中最基础的一种储存方式,与Java中的文件存储类似,都是通过I/O流的形式把数据直接存储到文件中。
文件存储分为两类
- 内部存储
- 外部存储
1.内部存储
将应用程序中的数据以文件的形式存储到应用中(该文件默认位于data/data/<packagename>/目录下),此时存储的文件会被其所在的应用程序私有化,如果其它应用程序想要操作本应用程序中的文件,则需要设置权限。当创建的应用程序被卸载时,其内部存储文件也随之被删除。
Android程序有着自己的一套安全模型,默认情况下任何应用程序的文件都是私有的,其它程序无法访问。
Android开发中,内部存储使用的是Context提供的
openFileOutput()方法openFileInput()方法这两个方法能够返回进行读写操作的
FileOutputStream对象FileInputStream对象
openFileOutput()方法:打开应用中对应的”输出流“,将数据存储到指定的文件中
FileOutputStream fos = openFileOutput(String name,int mode);
openFileInput()方法:打开应用中对应的”输入流“,读取指定文件中的数据
FileInputStream fis = openFileInput(String name);
-
name:表示文件名 -
mode:表示文件的操作模式,也就是读写文件的方式mode的取值有四种
- MODE_PRIVATE:该文件只能被当前程序读写
- MODE_APPEND:该文件的内容可以追加
- MODE_WORLD_READABLE:该文件的内容可以被其它程序读
- MODE_WORLD_WRITEABLE:该文件的内容可以被其它程序写
(1)存储数据
FileOutputStream对象可以将数据存储到文件中。
String fileName = "data.txt"; //文件名称
String content = "helloworld"; //要写入的数据
FileOutputStream fos = null;
try{
fos = openFileOutput(fileName,MODE_PRIVATE); //通过openFileOutput()方法返回FileOutputStream对象
fos.write(content.getBytes()); //通过FileOutputStream对象fos的write()方法将数据写入“data.txt”文件中
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(fos!=null){
fos.close(); //关闭输出流
}
}catch(IOException e){
e.printStackTrace();
}
}
(2)读取数据
FileInputStream对象能够读取内部存储中的数据
String content = "";
FileInputStream fis = null;
try{
fis = openFileInput("data.txt"); //获取文件输入流对象
byte[] buffer = new byte[fis.available()]; //创建缓冲区:通过available()获取文件长度,并创建相应大小的byte数据作为缓冲区
fis.read(buffer); //通过read()方法,将文件内容读取到buffer缓冲区
content = new String(buffer); //将读到的内容转换成指定字符串
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(fis!=null){
fis.close(); //关闭输入流
}
}catch(IOException e){
e.printStackTrace();
}
}
2.外部存储
将数据以文件的形式存储到一些外部设备上(SD卡,或设备内嵌的存储卡),属于永久性的存储方法(外部存储的文件通常位于mnt/sdcard目录下,不同的厂商生产的手机可能不同)。外部存储的文件可以被其它应用程序共享。
(1)存储数据
-
Environment.getExternalStroageState():确认外部设备是否可用(是否存在SD卡)当外部设备可用并且具有读写权限时,那么就可以通过
FileInputStream 和 FileOutputStream对象来读写外部设备中的文件 -
getExternalStroageDirectory():获取SD卡目录(避免将路径写成固定值而找不到SD卡)
String state = Enviroment.getExternalStroageState(); //获取外部设备的状态
if(state.equals(Enviroment.MEDIA_MOUNTED)){ //判断外部设备是否可用
File SDPath = Enviroment.getExternalStroageDirectory(); //获取SD卡目录
String file = new File(SDPath,"data.txt");
String data = "helloworld";
FileOutputStream fos = null;
try{
fos = new FileOutputStream(file); //创建文件输出流对象
fos.write(data.getBytes()); //将数据写入到文件中
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(fos!=null){
fos.close();
}
}catch(){
e.printStackTrace();
}
}
}
(2).读取数据
String state = Environment.getExternalStorageState(); //获取外部设备的状态
if(state.equals(Enviroment.MEDIA_MOUNTED)){ //判断外部设备是否可用
File SDPath = Enviroment.getRxternalStorageDirectory(); //获取SD卡目录
File file = new File(SDPath,"data.txt"); //创建文件对象
FileInputStream fis = null;
BufferedReader br = null;
try{
fis =new FileInputStream(file); //创建文件输入流对象
br = new BufferedReader(new InputStreamReader(fis)); //创建字符输入缓冲流的对象
String data = br.readLine(); //读取数据
}catch(Exception e){
e.printStackTrace();
}finally{
if(br!=null){
try{
br.close(); //关闭字符输入流
}catch(IOException e){
e.printStackTrace();
}
}
if(fis!=null){
try{
fis.close(); //关闭输入流
}catch(Exception e){
e.printStaceTrace();
}
}
}
}
3.SharedPreferences存储
SharedPreferences是Android平台上一个轻量级的存储类,用于持久化存储一些少量数据(例如:用户名,密码……)
1.将数据存入SharedPreferences中
//调用getSharedPreferences获取实例对象,
//(该对象本身只能获取数据,不能对数据存储和修改)
//data表示文件名,MODE_PRIVATE表示文件操作模式
SharedPreferences sp = getSharedPreferences("data",MODE_PRIVATE);
//获取编辑器,
//通过调用SharedPreferences类的edit()方法获取可编辑的Editor对象
SharedPreferences.Editor editor = sp.edit();
//通过Editor对象的putXXX()方法存储数据
eidtor.putString("name","传智播客"); //存入String类型数据
eidtor.putInt("age",8); //存入int类型数据
//提交修改
editor.commit();
SharedPreferences中的Editor编辑器是通过key/value(键值对)的形式存储数据,并且根据数据类型的不同,调用不同的方法- 数据保存在 【data/data/<paceagename>/shared_prefs】文件夹下XML文件中,
- 其中value值只能是
float、int、long、boolean、String、Set<String>类型数据
2.读取与删除SharedPreferences中的数据
(1)读取数据
//需要 获取 SharedPreferences对象
SharedPreferences sp = getSharedPreferences("data",MODE_PRIVATE);
//使用对象的getXXX()方法根据相应的key值获取到value的值
String data = sp.getString("name","")
getString()方法中的参数
name:key值- 第2个参数:缺省值(如果找不到该key,)
(2)删除数据
//只需要 调用 Editor对象的remove(String key)方法或者clear()方法
editor.remove("name"); //删除一条数据
editor.clear(); //删除所有数据
??????????????????????????????????????????????????
保存SharedPreferences的key值时,可以用静态变量保存,以免存储、删除时写错
例如:private static final String key = "incast";
4.SQLite数据库存储
用于存储程序中的”大量数据“,并对数据进行管理和维护
1.SQLite数据库的创建
创建一个类继承SQLiteOpenHelper类,在该类中重写onCreate()方法和onUpgrade方法
//继承SQLiteOpenHelper类
public class MyHelper extends SQLiteOpenHelper{
//重写该类的构造方法
//调用父类SQLIteOpenHelper的构造方法(此时会创建一个名为“itcast.db”的数据库)
public MyHpelper(Content content){
super(content,"itcast.db",null,2);
}
//oncreat()方法,数据库第一次被创建时调用该方法(通常用于初始化表结构)
public void onCreate(SQLiteDatabasre db){
//初始化数据库的表结构,执行一条连接表的SQL语句(以创建一个information表为例)
db.exeSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20),price INTERGET)");
}
//onUpgrade()方法,当数据库的版本号增加时调用(如果版本号不增加,则该方法不调用)
public void onUpgrade(SQLitedDatabase db,int oldVersion,int newVersion){
}
}
父类SQLiteOpenHelper构造方法的参数
content:上下文对象incast.db:数据库名称null:游标工厂(通常是null)2:数据库的版本
2.SQLite数据库的基本操作
1.新增数据
public void insert(String name,String price){
MyHelper helper = new MyHelper(MainActivity.this);
//获取可读写SQLiteDatabase对象
SQLiteDatabase db = helper.getWritableDatabase();
//创建ContentValues对象
//将数据添加到ContentValues对象
ContentValues values = new ContentValues();
values.put("name",name);
values.put("price",price);
//insert()方法,插入一条数据到information表
long id = db.insert("information",null,values);
//关闭数据库
db.close();
}
insert()方法中的参数
information:数据表的名称null:如果发现将要插入的行为空行时,会将这个列名的值设置为nullvlaues:ContentValues对象
ContentValues类类似于Map类,通过键值对的形式存入数据,key表示插入数据的列名,values表示插入的数据
2.删除数据
public void delete(long id){
//获取可读写SQLiteDatabase对象
SQLiteDatabase db = helper.getWritableDatabase();
//delete()方法,从information表中删除对应的数据
int number = db.delete("information","_id=?",new String[]{id+""});
db.close();
return number; //返回删除的行数
}
删除数据时不需要使用ContentValue对象来添加参数,而是使用一个“字符串”和“字符串数组”来添加“参数名”和“参数值”
3.修改数据
public void update(String name,String price){
SQLiteDatabase db = helper.getWritableDatabase();
//添加需要修改的“字段名”和“字段值”放到value对象中
ContentValues values = new ContentValues();
values.put("price",price);
//通过对象db调用update()方法来修改数据表中对应的数据
int number = db.update("information",values,"name=?",new String[]{name});
db.close();
return number; //返回修改的行数
}
update()中的参数
information:数据库表values:ContentValues对象(需要修改的最新的数据)name=?:要修改的数据的查询条件new String[]{name}:查找条件的参数
4.查询数据
public void find(int id){
MyHelper helper = new MyHelper(MainActivity.this);
//获取可读SQLiteDatabase对象
SQLiteDatabase db = helper.getReadableDatabase();
//通过query()方法查询数据
//
(返回的是一个行数集合Cursor,Cursor是一个游标接口,提供了遍历查询数据的方法)
Cursor cursor = db.query("infomation",null,"_id=?",new String[]{id+""},null,null,null);
//通过getCount()方法获取到查询结果的总数
//判断cursor有多少个数据,如果没有就不要进入循环了
if(cursor.getCount()!=0){
//通过moveToNext()方法移动游标指向下一行数据
while(cursor.moveToNext()){
//通过getString()方法传入列名获取数据
String _id = cursor.getString(Cursor.getColumnIndex("_id"));
String name = cursor.getString(Cursor.getColumnIndex("name"));
String price = cursor.getString(Cursor.getColumnIndex("price"));
}
}
cursor.close(); //关闭游标
db.close();
}
query()方法中的参数
information:数据表名称null:查询的列名_id=?:接收查询条件的子句new String[]{id+" "}:接受查询子句对应的条件值null:分组方式null:接受having条件(即定义组的过滤器)null:排序方式
??????????????????????????????????????????????????
通过SQL语句进行数据库的操作
还可以通过exeSQL()方法通过SQL语句对数据库尽心操作
- 增加一条数据
db.exeSQL("insert into information (name,price) values(?,?)",new Object[]{name,price});
- 删除一条数据
db.exeSQL("delete from information where _id=1");
- 修改一条数据
db.exeSQL("update information set name=? where price=?");
- 执行查询的SQL语句
Cursor cursor = db.rawQuery("select * from information where name=?",new Object[]{name,price});查询操作使用的是
rawQuery()方法,因为查询数据库会返回一个结果集Cursor,而exeSQL()方法没有返回值
3.SQLite数据库中的事务
ACID:数据库事务正确执行的四个基本要素的缩写
- 原子性(Atomicity):表示事务是一个不可在分割的单位,事务中的操作要么全部成功,要么全部失败回滚
- 一致性(Consistency):表示事务开始之前和结束之后,数据库的完整性没有被破坏(即数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性)
- 隔离性(Isolation):表示并发的事务是相互隔离的。(即一个事务内部的操作必须封锁起来,不会被其它事务影响到)
- 持久性(Durability):表示事务一旦提交后,该事务对数据做的更改便持久保存在数据库中,并不出现回滚
模拟银行转账功能
- 张三取出1000元时,王五存入1000元
PersonSQLiteOpenHelper helper = new PersonSQLiteOpenHelper(getApplication());
//获取一个可读写的SQLiteDatabase对象
SQLiteDatabase db = helper.getWritableDatabase();
//开始数据库的事务
db.beginTransaction();
try{
//执行转出操作
db.exeSQL("update person set account = account -1000 where name=?",new Object[]{"张三"});
//执行转入操作
db.exeSQL("update information set account = account +1000 where name=?",new Object[]{"王五"});
//标记数据库事务执行成功
db.setTransactionSuccessful();
}catch(Exception e){
Log.i("事务处理失败",e.toString());
}finally{
db.endTransaction(); //关闭事务
db.close(); //关闭数据库
}
事务操作完成后一定要使用endTransaction()方法关闭事务
当执行
endTransaction()方法时
- 首先,会检查是否有事务执行成功的标记
- 有,则提交数据
- 无,则回滚数据
- 最后,会关闭事务
如果不关闭事务,事务只有到超时才自动结束,会降低数据库并发效率,通常关闭事务的操作会在finally中执行

浙公网安备 33010602011771号