数据库存储全方案,详解持久化技术
来源:互联网 发布:安卓 windows 如何切换 编辑:程序博客网 时间:2024/05/16 11:23
1.介绍
数据的持久化就是将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不丢失。保存到内存中的数据是处于瞬时状态的,而保存在存储设备中的数据是处于持久状态的,持久化技术则是提供了一种机制可以让数据在瞬时状态和持久化之间进行转换。
2.Android系统提供了三种方式来简单的实现数据持久化技术:
文件存储:
(1)Android最基本的一种存储方式,原封不动的保存到文件中,比较适合存一些简单的文件数据或二进制数据,如果你想存一些比较复杂的文本数据,就需要定义一套自己的格式规范,这样方便之后将数据从文件中国重新解析出来。
(2)Context类提供了一个openFileOutput()方法,可以将数据存储到指定的文件中,这个方法接收两个参数,第一个参数是文件名,在文件创建的得时候就是用的的这个名称,注意这个文件名不可以包含路径,因为所有的文件到默认存储到/data/data//files/目录下的。第二个参数是文件的操作模式,主要有两种模式:MODE_PRIVATE和MODE_APPEND。其中MODE_PRIVATE是默认的操纵模式,表示指定同样文件名的时候,所写入的内容会覆盖原文件中的内容。而MODE_APPEND则表示的是追加内容,不存在就创建新文件。其实还有两种操作模式:MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,这两种模式表示允许对我们的文件进行读写操作,存在安全问题,Android 4.2已被废弃。
实例代码:》》》
/** * 下面我们是通过openFileOutput()方法得到一个FileOutputStream对象,然后再借助它构建出一个 OutputStreamWriter对象,接着在使用OutputStreamWriter构建出一个BufferedWriter对象,这样你就可以通过BufferWriter将文本内容写到文件中。 */public void save(String data) { FileOutputStream fos = null; BufferedWriter bw = null; try { fos = openFileOutput("data", Context.MODE_PRIVATE); bw = new BufferedWriter(new OutputStreamWriter(fos)); bw.write(data); } catch (IOException e) { e.printStackTrace(); } finally { try { if(bw != null) { bw.close(); } } catch (IOException e) { e.printStackTrace(); } }}
(3)文件存储路径:/data/data/自己的包名/files/你自己起的文件名:》》》
(4)Context还提供了一个openFileInput()方法,用于文件读取数据;
/** * 首先通过openFileInput()方法获取到了一个FielInputStream对象,然后借助它构建 一个inputStreamReader对象,接着在使用inputStreamReader构建出一个BufferedReader 对象,进行一行一行的读取 * @return */ public String load() { FileInputStream fis = null; BufferedReader br = null; StringBuilder sb = new StringBuilder(); try { fis = openFileInput("data"); br = new BufferedReader(new InputStreamReader(fis)); String line = ""; while((line = br.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if(br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); }
SharedPreferences存储:
-
(1)SharedPreferences是使用键值对(这个就不多说了)的方式来存储数据的。比使用文件存储更加方便。
(2)Context类中的getSharedPreferences()方法,第一个参数指定名称,不存在就创建一个,存放位置是存放在/data/data//shared_prefs/目录下的。第二个参数:用于指定操作模式,主要有两种模式可选,
MODE_PRIVATE和MODE_MULTI_PROCESS。MODE_PRIVATE仍然是操作的模式,和直接传入0效果相同,表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写,MODE_MULTI_PROCESS用于多个进程中对同一SharedPreferences进行读写,类似的,MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,这两种模式表示允许对我们的文件进行读写操作,存在安全问题,Android 4.2已被废弃。
(3)Activity类中的getPreferences()方法,只接收一个操作模式参数,使用这个方法会自动把当前活动的类名作为
SharedPreferences的文件名。
(4)PreferenceManager类中的getDefaultSharedPreferences()方法,这是一个静态方法。它接收一个context参数,并使用当前应用程序的包名作为前缀来命名SharedPreferences文件。
案例:
保存数据的第一种方式:
private SharedPreferences.Editor sp = getSharedPreferences("data",MODE_PRIVATE).edit(); sp.putString("name","tom"); sp.putInt("age",28); sp.putBoolean("married",false); sp.commit();
或者
SharedPreferences sharedPreferences = context.getSharedPreferences("userinfo.txt", Context.MODE_PRIVATE); //2.使用SharedPreference对象获取一个Editor对象 Editor editor = sharedPreferences.edit(); //3.往Editor对象中put键值对 editor.putString("username", username); editor.putString("password", password); //4.提交Editor对象 editor.commit();
恢复数据的案例:
SharedPreferences spre = getSharedPreferences("data",MODE_PRIVATE); boolean married = spre.getBoolean("married", false); int age = spre.getInt("age", 0); String name = spre.getString("name", ""); Log.d(TAG,"name="+name+" ,age="+age+" ,married="+married);
保存密码的案例:
//这里是登录记住密码的操作 final SharedPreferences spf = PreferenceManager.getDefaultSharedPreferences(this); final EditText uersname = (EditText) findViewById(R.id.et_username); final EditText password = (EditText) findViewById(R.id.et_password); final CheckBox cb_pass = (CheckBox) findViewById(R.id.remeber_pass); final boolean isRemember = spf.getBoolean("remember_password",false); if(isRemember) { //记住密码,设置为true uersname.setText(spf.getString("username","")); password.setText(spf.getString("password","")); cb_pass.setChecked(true); } Button login = (Button) findViewById(R.id.login); login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String user = uersname.getText().toString(); String pass = password.getText().toString(); if(user.equals("admin") && pass.equals("123456")) { editor = spf.edit(); if(cb_pass.isChecked()) { editor.putString("username",user); editor.putString("password",pass); editor.putBoolean("remember_password",true); } else { editor.clear(); } editor.commit(); Toast.makeText(MainActivity.this,"login success",Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this,"login fail",Toast.LENGTH_SHORT).show(); } } });
下面的图像是getDefaultSharedPreferences方法已包名为文件名:
这里要注意点 是当我们记住密码的时候用editor直接提交就可以了,在没有记住密码的时候要把简单的调用一下editor.clear()就可以了。
- 数据库存储。Sqlite
(1)Sqlite是一款轻量级的关系型数据库,小型的嵌入式数据库,只能对数据库进行操作。适合在移动设备上使用,sqlite不仅支持标准的sql语法,还遵循了数据的ACID事务,比一般的数据库简单的多。当需要存储大量复杂的关系型数据的时候,上面两种方式很难应付,这时候我们就用sqlite数据库来存储数据。
(2)创建数据库,Android专门提供了SQliteOpenHelper帮助类,借助这个类可以非常简单的对数据库进行创建和升级,这个类是一个抽象类,里面有两个抽象方法,分别是onCreate()和onUpgrade(),然后分别在这两个方法中实现创建、升级数据库的逻辑。
(3)SQliteOpenHelper中还有两个非常重要的实例方法,getReadableDatabase()和getWritableDatabase(),这两个方法都可以创建和打开一个现有的数据库,并返回一个可对数据库进行读写操作的对象,不同的是,当数据库不可写入的时候(如磁盘空间已满)getReadableDatabase()方法返回的对象将以只读的方式打开数据库,而getWritableDatabase()方法则将抛出异常。
(4)SQliteOpenHelper中有两个构造方法可重写,一般使用参数少一点的即可,构造方法中接收四个参数,第一个参数是Context,第二个参数是数据库名,第三个参数允许我们在查询数据的时候返回一个自定义的Cursor,一般都是传入null,第四个参数表示当前数据库的版本号,可用于对数据库进行升级的操作。构建出SQliteOpenHelper实例之后,再调用它的getReadableDatabase()或getWritableDatabase()方法就能够创建数据库了,数据库文件的存放位置/data/data//database/目录下,重写的onCreate方法也会执行。
数据类型: integer表示整型 real表示浮点型 text表示文本类型 blob表示二进制类型 命令行查看sqlite数据库: 启动模拟器 命令行cd 到android-sdk-windows\platform-tools目录 adb shell //进入模拟器 cd /data/data/yourpackagename/ //进入到软件安装目录 cd databases //进入到数据库目录 ls //查看现有的数据库,如果创建过应该有个XXXX.db sqlite3 XXXX.db //用sqlite3工具打开数据库,如果不行的话,直接sqlite3 xxxx //下面是sqlite3命令 sqlite> .tables //查看数据库里面的表 本例应该能看到表YYYY sqlite> .schema YYYY //查看表结构 sqlite> select * from YYYY; //查询表
(5)像上面所说的数据库升级的方法是非常粗暴的,我们只是简单的在onUpgrade方法中删除了所有的表,然后重新强制执行了一遍onCreate方法,如果产品上线这样做是不可以的,如果用户在更新版本的时候发现以前的数据全部丢失了,那么这个客户就丢失了。
(6)数据库升级的时候是不能丢失数据的,就是在第一个版本安装的时候,就要把所有的表以及升级之后的表都要建好,第二个版本升级第三个版本也要添加表,保证用户无论怎么升级都是最新的表就对了。
重点:另外,我们也可以存储在SD卡当中,不过以上三种保存数据会相对来说更简单一些,相比SD卡会更加安全。
案例:
/** * 添加数据 */ bt_add = (Button) findViewById(R.id.add_data); bt_add.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SQLiteDatabase db = helper.getWritableDatabase(); ContentValues values = new ContentValues(); //添加第一组数据 values.put("name","zhangsan"); values.put("auther","Ban brown1"); values.put("pages",145); values.put("price",13.45); db.insert("Book",null,values);//插入第一天数据 values.clear(); //添加第二组数据 values.put("name","lisi"); values.put("auther","Ban brown2"); values.put("pages",111); values.put("price",3.89); db.insert("Book",null,values);//插入第二条数据 } });
删除:
/** * 删除数据 */ Button bt_delete = (Button) findViewById(R.id.delete_data); bt_delete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SQLiteDatabase db = helper.getWritableDatabase(); db.delete("Book","pages > ?",new String[] {"140"}); } });
query获取数据方法参数:
获取数据:
/** * 获取数据 * */ Button bt_query = (Button) findViewById(R.id.query_data); bt_query.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SQLiteDatabase db = helper.getReadableDatabase(); //查询Book表中所有的数据 Cursor cursor = db.query("Book",null,null,null,null,null,null); /** * 这里先进行判断是否是在第一行,如果是,直接获取数据,然后再判断是否有 * 下一行,进行while循环的判断,去遍历查询每一行数据,cursor.getColumnIndex * 方法会获取到某一列在表中对应的位置索引。 */ if(cursor.moveToFirst()) { do { String name = cursor.getString(cursor.getColumnIndex("name")); String auther = cursor.getString(cursor.getColumnIndex("auther")); int pages = cursor.getInt(cursor.getColumnIndex("pages")); double price = cursor.getInt(cursor.getColumnIndex("price")); Log.d(TAG,"name = "+name); Log.d(TAG,"auther = "+auther); Log.d(TAG,"pages = "+pages); Log.d(TAG,"price = "+price); } while (cursor.moveToNext()); } cursor.close(); } });
修改:
/** * 更改数据 */ Button bt_update = (Button) findViewById(R.id.update_data); bt_update.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SQLiteDatabase db = helper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("price",888); db.update("Book",values,"name=?",new String[] {"lisi"}); } });
开启事务,进行数据的替换操作:
/** * 开启事务,进行数据的替换操作 */ Button bt_replace = (Button) findViewById(R.id.replace_data); bt_replace.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SQLiteDatabase db = helper.getWritableDatabase(); db.beginTransaction();//开启事务 try { db.delete("Book",null,null); /** * 如果在这里抛出一个异常,出现问题,有了事务,执行失败,数据就不会被替换 * 如果去掉,事务执行成功就会被替换。 */ if(true) { //在这里手动抛出一个异常,让事务失败// throw new NullPointerException(); } ContentValues values = new ContentValues(); values.put("name","wangwu"); values.put("auther","Ban brown3"); values.put("pages",140); values.put("price",13); db.insert("Book",null,values); db.setTransactionSuccessful();//执行事务成功 } catch (Exception e) { e.printStackTrace(); } finally { db.endTransaction();//事务结束 } } });
得到数据库的帮助类以及创建表的操作:
private static final String CREATE_BOOK = "create table Book (" + "id integer, " + "auther text, " + "price real, " + "pages integer, " + "name text, " + "primary key(id,auther)" + ")";private static final String CREATE_CATRGORY = "create table Category (" + "_id integer primary key autoincrement, " + "category_name text, " + "category_code integer)";/** * 得到创建数据库的帮助类 * @param context * @return */public static synchronized DatabaseHelper getInstance(Context context) { if (instance == null) { instance = new DatabaseHelper(context); } return instance;}
下面是数据库直接对数据的操作:
- 数据库存储全方案,详解持久化技术
- 第六章 数据存储全方案,详解持久化技术
- 数据存储全方案,详解持久化技术
- 数据存储全方案,详解持久化技术
- 数据存储全方案,详解持久化技术
- android 摘要----数据存储全方案,详解持久化技术
- 第六章 数据存储全方案-详解持久化技术
- 数据存储全方案,详解持久化技术
- 数据存储全方案--详解持久化技术
- 数据存储全方案--详解持久化技术
- Android学习之 第 6 章 数据存储全方案,详解 持久化技术
- Android学习之 第 6 章 数据存储全方案,详解 持久化技术
- day05 数据存储方案,详解持久化技术
- 数据存储方案:持久化技术
- 第一行代码读书笔记——数据存储全方案,持久化技术
- 阅读郭林《第一行代码》的笔记——第6章 数据存储全方案,详解持久化技术
- 数据存储--------详解持久化技术
- Android 开发实践 数据存储方案 持久化技术
- 解决cocos2dx 3.12版本使用PageView调用addEventListener函数,参数不明问题
- java程序向mysql数据库插入数据中文 乱码问题解决
- 设备树
- 字符串单词反转
- SDUT2134数据结构实验之栈四:括号匹配(栈)
- 数据库存储全方案,详解持久化技术
- linux之shell
- MySQL 入门(上)
- 关于PAT 1004 Counting leaves 的疑问
- java虚拟机系列--内存分配与垃圾回收机制
- Java进阶之内存管理与垃圾回收
- poj 2377 Bad Cowtractors
- 使用Jedis连接Redis
- 拷贝继承(call+拷贝继承)