5种Android数据存储方式汇总
本文介绍android中的5种数据存储方式。
数据存储在开发中是使用最频繁的,在这里主要介绍android平台中实现数据存储的5种方式,分别是:
1 使用sharedpreferences存储数据
2 文件存储数据
3 sqlite数据库存储数据
4 使用contentprovider存储数据
5 网络存储数据
下面将为大家一一详细介绍。
第一种:使用sharedpreferences存储数据
sharedpreferences是android平台上一个轻量级的存储类,主要是保存一些常用的配置比如窗口状态,一般在activity中 重载窗口状态onsaveinstancestate保存一般使用sharedpreferences完成,它提供了android平台常规的long长 整形、int整形、string字符串型的保存。
它是什么样的处理方式呢? sharedpreferences类似过去windows系统上的ini配置文件,但是它分为多种权限,可以全局共享访问,android123提示最终是以xml方式来保存,整体效率来看不是特别的高,对于常规的轻量级而言比sqlite要好不少,如果真的存储量不大可以考虑自己定义文件格式。xml 处理时dalvik会通过自带底层的本地xml parser解析,比如xmlpull方式,这样对于内存资源占用比较好。
它的本质是基于xml文件存储key-value键值对数据,通常用来存储一些简单的配置信息。
其存储位置在/data/data/< >/shared_prefs目录下。
sharedpreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过editor对象实现。
实现sharedpreferences存储的步骤如下:
step1、根据context获取sharedpreferences对象
step2、利用edit()方法获取editor对象。
step3、通过editor对象存储key-value键值对数据。
step4、通过commit()方法提交数据。
下面是示例代码:
public class mainactivity extends activity { @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); //获取sharedpreferences对象 context ctx = mainactivity.this; sharedpreferences sp = ctx.getsharedpreferences("sp", mode_private); //存入数据 editor editor = sp.edit(); editor.putstring("string_key", "string"); editor.putint("int_key", 0); editor.putboolean("boolean_key", true); editor.commit(); //返回string_key的值 log.d("sp", sp.getstring("string_key", "none")); //如果not_exist不存在,则返回值为"none" log.d("sp", sp.getstring("not_exist", "none")); } }
这段代码执行过后,即在/data/data/com.test/shared_prefs目录下生成了一个sp.xml文件,一个应用可以创建多个这样的xml文件。
sharedpreferences对象与sqlite数据库相比,免去了创建数据库,创建表,写sql语句等诸多操作,相对而言更加方便,简洁。但是sharedpreferences也有其自身缺陷,比如其职能存储boolean,int,float,long和string五种简单的数据类型,比如其无法进行条件查询等。所以不论sharedpreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如sqlite数据库这样的其他数据存储方式。
第二种:文件存储数据
关于文件存储,activity提供了openfileoutput()方法可以用于把数据输出到文件中,具体的实现过程与在j2se环境中保存数据到文件中是一样的。
文件可用来存放大量数据,如文本、图片、音频等。
默认位置:/data/data/< >/files/.。
代码示例:
public void save() { try { fileoutputstream outstream=this.openfileoutput("a.txt",context.mode_world_readable); outstream.write(text.gettext().tostring().getbytes()); outstream.close(); toast.maketext(myactivity.this,"saved",toast.length_long).show(); } catch (filenotfoundexception e) { return; } catch (ioexception e){ return ; } }
openfileoutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,android 会自动创建它。
创建的文件保存在/data/data//files目录,如: /data/data/cn.itcast.action/files/itcast.txt ,通过点击eclipse菜单“window”-“show view”-“other”,在对话窗口中展开android文件夹,选择下面的file explorer视图,然后在file explorer视图中展开/data/data//files目录就可以看到该文件。
openfileoutput()方法的第二参数用于指定操作模式,有四种模式,分别为:
context.mode_private = 0
context.mode_append = 32768
context.mode_world_readable = 1
context.mode_world_writeable = 2
context.mode_private:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用context.mode_append
context.mode_append:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
context.mode_world_readable和context.mode_world_writeable用来控制其他应用是否有权限读写该文件。
mode_world_readable:表示当前文件可以被其他应用读取;
mode_world_writeable:表示当前文件可以被其他应用写入。
如果希望文件被其他应用读和写,可以传入: openfileoutput(“itcast.txt”, context.mode_world_readable + context.mode_world_writeable); android有一套自己的安全模型,当应用程序(.apk)在安装时系统就会分配给他一个userid,当该应用要去访问其他资源比如文件的时候,就需要userid匹配。默认情况下,任何应用创建的文件,sharedpreferences,数据库都应该是私有的(位于/data/data//files),其他程序无法访问。
除非在创建时指定了context.mode_world_readable或者context.mode_world_writeable ,只有这样其他程序才能正确访问。
读取文件示例:
public void load() { try { fileinputstream instream=this.openfileinput("a.txt"); bytearrayoutputstream stream=new bytearrayoutputstream(); byte[] buffer=new byte[1024]; int length=-1; while((length=instream.read(buffer))!=-1) { stream.write(buffer,0,length); } stream.close(); instream.close(); text.settext(stream.tostring()); toast.maketext(myactivity.this,"loaded",toast.length_long).show(); } catch (filenotfoundexception e) { e.printstacktrace(); } catch (ioexception e){ return ; } }
对于私有文件只能被创建该文件的应用访问,如果希望文件能被其他应用读和写,可以在创建文件时,指定context.mode_world_readable和context.mode_world_writeable权限。
activity还提供了getcachedir()和getfilesdir()方法: getcachedir()方法用于获取/data/data//cache目录 getfilesdir()方法用于获取/data/data//files目录。
把文件存入sdcard:
使用activity的openfileoutput()方法保存文件,文件是存放在手机空间上,一般手机的存储空间不是很大,存放些小文件还行,如果要存放像视频这样的大文件,是不可行的。对于像视频这样的大文件,我们可以把它存放在sdcard。
sdcard是干什么的?你可以把它看作是移动硬盘或u盘。 在模拟器中使用sdcard,你需要先创建一张sdcard卡(当然不是真的sdcard,只是镜像文件)。
创建sdcard可以在eclipse创建模拟器时随同创建,也可以使用dos命令进行创建,如下: 在dos窗口中进入android sdk安装路径的tools目录,输入以下命令创建一张容量为2g的sdcard,文件后缀可以随便取,建议使用.img: mksdcard 2048m d:\androidtool\sdcard.img 在程序中访问sdcard,你需要申请访问sdcard的权限。
在androidmanifest.xml中加入访问sdcard的权限如下:
<!-- 在sdcard中创建与删除文件权限 --> <uses-permission android:name="android.permission.mount_unmount_filesystems"/> <!-- 往sdcard写入数据权限 --> <uses-permission android:name="android.permission.write_external_storage"/>
要往sdcard存放文件,程序必须先判断手机是否装有sdcard,并且可以进行读写。
注意:访问sdcard必须在androidmanifest.xml中加入访问sdcard的权限。
if(environment.getexternalstoragestate().equals(environment.media_mounted)){ file sdcarddir = environment.getexternalstoragedirectory();//获取sdcard目录 file savefile = new file(sdcarddir, “a.txt”); fileoutputstream outstream = new fileoutputstream(savefile); outstream.write("test".getbytes()); outstream.close(); }
environment.getexternalstoragestate()方法用于获取sdcard的状态,如果手机装有sdcard,并且可以进行读写,那么方法返回的状态等于environment.media_mounted。
environment.getexternalstoragedirectory()方法用于获取sdcard的目录,当然要获取sdcard的目录,你也可以这样写:
file sdcarddir = new file("/sdcard"); //获取sdcard目录 file savefile = new file(sdcarddir, "itcast.txt"); //上面两句代码可以合成一句: file savefile = new file("/sdcard/a.txt"); fileoutputstream outstream = new fileoutputstream(savefile); outstream.write("test".getbytes()); outstream.close();
第三种:sqlite数据库存储数据
sqlite是轻量级嵌入式数据库引擎,它支持 sql 语言,并且只利用很少的内存就有很好的性能。此外它还是开源的,任何人都可以使用它。许多开源项目((mozilla, php, python)都使用了 sqlite.sqlite 由以下几个组件组成:sql 编译器、内核、后端以及附件。sqlite 通过利用虚拟机和虚拟数据库引擎(vdbe),使调试、修改和扩展 sqlite 的内核变得更加方便。
特点:
面向资源有限的设备,
没有服务器进程,
所有数据存放在同一文件中跨平台,
可*复制。
sqlite 内部结构:
sqlite 基本上符合 sql-92 标准,和其他的主要 sql 数据库没什么区别。它的优点就是高效,android 运行时环境包含了完整的 sqlite。
sqlite 和其他数据库最大的不同就是对数据类型的支持,创建一个表时,可以在 create table 语句中指定某列的数据类型,但是你可以把任何数据类型放入任何列中。当某个值插入数据库时,sqlite 将检查它的类型。如果该类型与关联的列不匹配,则 sqlite 会尝试将该值转换成该列的类型。如果不能转换,则该值将作为其本身具有的类型存储。比如可以把一个字符串(string)放入 integer 列。sqlite 称这为“弱类型”(manifest typing.)。 此外,sqlite 不支持一些标准的 sql 功能,特别是外键约束(foreign key constrains),嵌套 transcaction 和 right outer join 和 full outer join, 还有一些 alter table 功能。 除了上述功能外,sqlite 是一个完整的 sql 系统,拥有完整的触发器,交易等等。
android 集成了 sqlite 数据库 android 在运行时(run-time)集成了 sqlite,所以每个 android 应用程序都可以使用 sqlite 数据库。
对于熟悉 sql 的开发人员来时,在 android 开发中使用 sqlite 相当简单。但是,由于 jdbc 会消耗太多的系统资源,所以 jdbc 对于手机这种内存受限设备来说并不合适。因此,android 提供了一些新的 api 来使用 sqlite 数据库,android 开发中,程序员需要学使用这些 api。
数据库存储在 data/< 项目文件夹 >/databases/ 下。 android 开发中使用 sqlite 数据库 activites 可以通过 content provider 或者 service 访问一个数据库。
下面会详细讲解如果创建数据库,添加数据和查询数据库。 创建数据库 android 不自动提供数据库。在 android 应用程序中使用 sqlite,必须自己创建数据库,然后创建表、索引,填充数据。
android 提供了 sqliteopenhelper 帮助你创建一个数据库,你只要继承 sqliteopenhelper 类,就可以轻松的创建数据库。sqliteopenhelper 类根据开发应用程序的需要,封装了创建和更新数据库使用的逻辑。
sqliteopenhelper 的子类,至少需要实现三个方法:
1 构造函数,调用父类 sqliteopenhelper 的构造函数。这个方法需要四个参数:上下文环境(例如,一个 activity),数据库名字,一个可选的游标工厂(通常是 null),一个代表你正在使用的数据库模型版本的整数。
2 oncreate()方法,它需要一个 sqlitedatabase 对象作为参数,根据需要对这个对象填充表和初始化数据。
3 onupgrage() 方法,它需要三个参数,一个 sqlitedatabase 对象,一个旧的版本号和一个新的版本号,这样你就可以清楚如何把一个数据库从旧的模型转变到新的模型。
下面示例代码展示了如何继承 sqliteopenhelper 创建数据库:
public class databasehelper extends sqliteopenhelper { databasehelper(context context, string name, cursorfactory cursorfactory, int version) { super(context, name, cursorfactory, version); } @override public void oncreate(sqlitedatabase db) { // todo 创建数据库后,对数据库的操作 } @override public void onupgrade(sqlitedatabase db, int oldversion, int newversion) { // todo 更改数据库版本的操作 } @override public void onopen(sqlitedatabase db) { super.onopen(db); // todo 每次成功打开数据库后首先被执行 } }
接下来讨论具体如何创建表、插入数据、删除表等等。调用 getreadabledatabase() 或 getwriteabledatabase() 方法,你可以得到 sqlitedatabase 实例,具体调用那个方法,取决于你是否需要改变数据库的内容:
db=(new databasehelper(getcontext())).getwritabledatabase(); return (db == null) ? false : true;
上面这段代码会返回一个 sqlitedatabase 类的实例,使用这个对象,你就可以查询或者修改数据库。 当你完成了对数据库的操作(例如你的 activity 已经关闭),需要调用 sqlitedatabase 的 close() 方法来释放掉数据库连接。 创建表和索引 为了创建表和索引,需要调用 sqlitedatabase 的 execsql() 方法来执行 ddl 语句。如果没有异常,这个方法没有返回值。
例如,你可以执行如下代码:
db.execsql("create table mytable (_id integer primary key autoincrement, title text, value real);");
这条语句会创建一个名为 mytable 的表,表有一个列名为 _id,并且是主键,这列的值是会自动增长的整数(例如,当你插入一行时,sqlite 会给这列自动赋值),另外还有两列:title( 字符 ) 和 value( 浮点数 )。 sqlite 会自动为主键列创建索引。 通常情况下,第一次创建数据库时创建了表和索引。
如果你不需要改变表的 schema,不需要删除表和索引 . 删除表和索引,需要使用 execsql() 方法调用 drop index 和 drop table 语句。 给表添加数据 上面的代码,已经创建了数据库和表,现在需要给表添加数据。有两种方法可以给表添加数据。
像上面创建表一样,你可以使用 execsql() 方法执行 insert, update, delete 等语句来更新表的数据。execsql() 方法适用于所有不返回结果的 sql 语句。
例如: db.execsql(“insert into widgets (name, inventory)”+ “values (‘sprocket', 5)”);
另一种方法是使用 sqlitedatabase 对象的 insert(), update(), delete() 方法。这些方法把 sql 语句的一部分作为参数。
示例如下:
contentvalues cv=new contentvalues(); cv.put(constants.title, "example title"); cv.put(constants.value, sensormanager.gravity_death_star_i); db.insert("mytable", getnullcolumnhack(), cv);
update()方法有四个参数,分别是表名,表示列名和值的 contentvalues 对象,可选的 where 条件和可选的填充 where 语句的字符串,这些字符串会替换 where 条件中的“?”标记。
update() 根据条件,更新指定列的值,所以用 execsql() 方法可以达到同样的目的。 where 条件和其参数和用过的其他 sql apis 类似。
例如:
string[] parms=new string[] {“this is a string”}; db.update(“widgets”, replacements, “name=?”, parms);
delete() 方法的使用和 update() 类似,使用表名,可选的 where 条件和相应的填充 where 条件的字符串。 查询数据库 类似 insert, update, delete,有两种方法使用 select 从 sqlite 数据库检索数据。
1.使用 rawquery() 直接调用 select 语句; 使用 query() 方法构建一个查询。
raw queries 正如 api 名字,rawquery() 是最简单的解决方法。通过这个方法你就可以调用 sql select 语句。
例如: cursor c=db.rawquery( “select name from sqlite_master where type='table' and name='mytable'”, null);
在上面例子中,我们查询 sqlite 系统表(sqlite_master)检查 table 表是否存在。返回值是一个 cursor 对象,这个对象的方法可以迭代查询结果。 如果查询是动态的,使用这个方法就会非常复杂。
例如,当你需要查询的列在程序编译的时候不能确定,这时候使用 query() 方法会方便很多。
regular queries query() 方法用 select 语句段构建查询。select 语句内容作为 query() 方法的参数,比如:要查询的表名,要获取的字段名,where 条件,包含可选的位置参数,去替代 where 条件中位置参数的值,group by 条件,having 条件。 除了表名,其他参数可以是 null。所以,以前的代码段可以可写成:
string[] columns={“id”, “inventory”}; string[] parms={“snicklefritz”}; cursor result=db.query(“widgets”, columns, “name=?”,parms, null, null, null);
使用游标
不管你如何执行查询,都会返回一个 cursor,这是 android 的 sqlite 数据库游标,
使用游标,你可以:
通过使用 getcount() 方法得到结果集中有多少记录;
通过 movetofirst(), movetonext(), 和 isafterlast() 方法遍历所有记录;
通过 getcolumnnames() 得到字段名;
通过 getcolumnindex() 转换成字段号;
通过 getstring(),getint() 等方法得到给定字段当前记录的值;
通过 requery() 方法重新执行查询得到游标;
通过 close() 方法释放游标资源;
例如,下面代码遍历 mytable 表:
cursor result=db.rawquery(“select id, name, inventory from mytable”); result.movetofirst(); while (!result.isafterlast()) { int id=result.getint(0); string name=result.getstring(1); int inventory=result.getint(2); // do something useful with these result.movetonext(); } result.close();
在android 中使用 sqlite 数据库管理工具 在其他数据库上作开发,一般都使用工具来检查和处理数据库的内容,而不是仅仅使用数据库的 api。
使用 android 模拟器,有两种可供选择的方法来管理数据库。
首先,模拟器绑定了 sqlite3 控制台程序,可以使用 adb shell 命令来调用他。只要你进入了模拟器的 shell,在数据库的路径执行 sqlite3 命令就可以了。
数据库文件一般存放在: /data/data/your.app.package/databases/your-db-name 如果你喜欢使用更友好的工具,你可以把数据库拷贝到你的开发机上,使用 sqlite-aware 客户端来操作它。这样的话,你在一个数据库的拷贝上操作,如果你想要你的修改能反映到设备上,你需要把数据库备份回去。
把数据库从设备上考出来,你可以使用 adb pull 命令(或者在 ide 上做相应操作)。
存储一个修改过的数据库到设备上,使用 adb push 命令。 一个最方便的 sqlite 客户端是 firefox sqlite manager 扩展,它可以跨所有平台使用。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。