Android编程中的5种数据存储方式
本文介绍android平台进行数据存储的五大方式,分别如下:
1 使用sharedpreferences存储数据
2 文件存储数据
3 sqlite数据库存储数据
4 使用contentprovider存储数据
5 网络存储数据
下面详细讲解这五种方式的特点
第一种: 使用sharedpreferences存储数据
适用范围:保存少量的数据,且这些数据的格式非常简单:字符串型、基本类型的值。比如应用程序的各种配置信息(如是否打开音效、是否使用震动效果、小游戏的玩家积分等),解锁口 令密码等
核心原理:保存基于xml文件存储的key-value键值对数据,通常用来存储一些简单的配置信息。通过ddms的file explorer面板,展开文件浏览树,很明显sharedpreferences数据总是存储在/data/data/<package name>/shared_prefs目录下。sharedpreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过sharedpreferences.edit()获取的内部接口editor对象实现。 sharedpreferences本身是一 个接口,程序无法直接创建sharedpreferences实例,只能通过context提供的getsharedpreferences(string name, int mode)方法来获取sharedpreferences实例,该方法中name表示要操作的xml文件名,第二个参数具体如下:
context.mode_private: 指定该sharedpreferences数据只能被本应用程序读、写。
context.mode_world_readable: 指定该sharedpreferences数据能被其他应用程序读,但不能写。
context.mode_world_writeable: 指定该sharedpreferences数据能被其他应用程序读,写
editor有如下主要重要方法:
sharedpreferences.editor clear():清空sharedpreferences里所有数据
sharedpreferences.editor putxxx(string key , xxx value): 向sharedpreferences存入指定key对应的数据,其中xxx 可以是boolean,float,int等各种基本类型据
sharedpreferences.editor remove(): 删除sharedpreferences中指定key对应的数据项
boolean commit(): 当editor编辑完成后,使用该方法提交修改
实际案例:运行界面如下
这里只提供了两个按钮和一个输入文本框,布局简单,故在此不给出界面布局文件了,程序核心代码如下:
class viewocl implements view.onclicklistener{ @override public void onclick(view v) { switch(v.getid()){ case r.id.btnset: //步骤1:获取输入值 string code = txtcode.gettext().tostring().trim(); //步骤2-1:创建一个sharedpreferences.editor接口对象,lock表示要写入的xml文件名,mode_world_writeable写操作 sharedpreferences.editor editor = getsharedpreferences("lock", mode_world_writeable).edit(); //步骤2-2:将获取过来的值放入文件 editor.putstring("code", code); //步骤3:提交 editor.commit(); toast.maketext(getapplicationcontext(), "口令设置成功", toast.length_long).show(); break; case r.id.btnget: //步骤1:创建一个sharedpreferences接口对象 sharedpreferences read = getsharedpreferences("lock", mode_world_readable); //步骤2:获取文件中的值 string value = read.getstring("code", ""); toast.maketext(getapplicationcontext(), "口令为:"+value, toast.length_long).show(); break; } } }
读写其他应用的sharedpreferences: 步骤如下
1、在创建sharedpreferences时,指定mode_world_readable模式,表明该sharedpreferences数据可以被其他程序读取
2、创建其他应用程序对应的context:
context pvcount = createpackagecontext("com.tony.app", context.context_ignore_security);这里的com.tony.app就是其他程序的包名
3、使用其他程序的context获取对应的sharedpreferences
sharedpreferences read = pvcount.getsharedpreferences("lock", context.mode_world_readable);
4、如果是写入数据,使用editor接口即可,所有其他操作均和前面一致。
sharedpreferences对象与sqlite数据库相比,免去了创建数据库,创建表,写sql语句等诸多操作,相对而言更加方便,简洁。但是sharedpreferences也有其自身缺陷,比如其职能存储boolean,int,float,long和string五种简单的数据类型,比如其无法进行条件查询等。所以不论sharedpreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如sqlite数据库这样的其他数据存储方式。
第二种: 文件存储数据
核心原理: context提供了两个方法来打开数据文件里的文件io流 fileinputstream openfileinput(string name); fileoutputstream(string name , int mode),这两个方法第一个参数 用于指定文件名,第二个参数指定打开文件的模式。具体有以下值可选:
mode_private:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可 以使用context.mode_append
mode_append:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
mode_world_readable:表示当前文件可以被其他应用读取;
mode_world_writeable:表示当前文件可以被其他应用写入。
除此之外,context还提供了如下几个重要的方法:
getdir(string name , int mode):在应用程序的数据文件夹下获取或者创建name对应的子目录
file getfilesdir():获取该应用程序的数据文件夹得绝对路径
string[] filelist():返回该应用数据文件夹的全部文件
实际案例:界面沿用上图
核心代码如下:
public string read() { try { fileinputstream instream = this.openfileinput("message.txt"); byte[] buffer = new byte[1024]; int hasread = 0; stringbuilder sb = new stringbuilder(); while ((hasread = instream.read(buffer)) != -1) { sb.append(new string(buffer, 0, hasread)); } instream.close(); return sb.tostring(); } catch (exception e) { e.printstacktrace(); } return null; } public void write(string msg){ // 步骤1:获取输入值 if(msg == null) return; try { // 步骤2:创建一个fileoutputstream对象,mode_append追加模式 fileoutputstream fos = openfileoutput("message.txt", mode_append); // 步骤3:将获取过来的值放入文件 fos.write(msg.getbytes()); // 步骤4:关闭数据流 fos.close(); } catch (exception e) { e.printstacktrace(); } }
openfileoutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,android 会自动创建它。创建的文件保存在/data/data/<package name>/files目录,如: /data/data/cn.tony.app/files/message.txt,
下面讲解某些特殊文件读写需要注意的地方:
读写sdcard上的文件
其中读写步骤按如下进行:
1、调用environment的getexternalstoragestate()方法判断手机上是否插了sd卡,且应用程序具有读写sd卡的权限,如下代码将返回true
environment.getexternalstoragestate().equals(environment.media_mounted)
2、调用environment.getexternalstoragedirectory()方法来获取外部存储器,也就是sd卡的目录,或者使用"/mnt/sdcard/"目录
3、使用io流操作sd卡上的文件
注意点:手机应该已插入sd卡,对于模拟器而言,可通过mksdcard命令来创建虚拟存储卡
必须在androidmanifest.xml上配置读写sd卡的权限
<uses-permission android:name="android.permission.mount_unmount_filesystems"/> <uses-permission android:name="android.permission.write_external_storage"/>
案例代码:
// 文件写操作函数 private void write(string content) { if (environment.getexternalstoragestate().equals( environment.media_mounted)) { // 如果sdcard存在 file file = new file(environment.getexternalstoragedirectory() .tostring() + file.separator + dir + file.separator + filename); // 定义file类对象 if (!file.getparentfile().exists()) { // 父文件夹不存在 file.getparentfile().mkdirs(); // 创建文件夹 } printstream out = null; // 打印流对象用于输出 try { out = new printstream(new fileoutputstream(file, true)); // 追加文件 out.println(content); } catch (exception e) { e.printstacktrace(); } finally { if (out != null) { out.close(); // 关闭打印流 } } } else { // sdcard不存在,使用toast提示用户 toast.maketext(this, "保存失败,sd卡不存在!", toast.length_long).show(); } } // 文件读操作函数 private string read() { if (environment.getexternalstoragestate().equals( environment.media_mounted)) { // 如果sdcard存在 file file = new file(environment.getexternalstoragedirectory() .tostring() + file.separator + dir + file.separator + filename); // 定义file类对象 if (!file.getparentfile().exists()) { // 父文件夹不存在 file.getparentfile().mkdirs(); // 创建文件夹 } scanner scan = null; // 扫描输入 stringbuilder sb = new stringbuilder(); try { scan = new scanner(new fileinputstream(file)); // 实例化scanner while (scan.hasnext()) { // 循环读取 sb.append(scan.next() + "\n"); // 设置文本 } return sb.tostring(); } catch (exception e) { e.printstacktrace(); } finally { if (scan != null) { scan.close(); // 关闭打印流 } } } else { // sdcard不存在,使用toast提示用户 toast.maketext(this, "读取失败,sd卡不存在!", toast.length_long).show(); } return null; }
第三种:sqlite存储数据
sqlite是轻量级嵌入式数据库引擎,它支持 sql 语言,并且只利用很少的内存就有很好的性能。现在的主流移动设备像android、iphone等都使用sqlite作为复杂数据的存储引擎,在我们为移动设备开发应用程序时,也许就要使用到sqlite来存储我们大量的数据,所以我们就需要掌握移动设备上的sqlite开发技巧
sqlitedatabase类为我们提供了很多种方法,上面的代码中基本上囊括了大部分的数据库操作;对于添加、更新和删除来说,我们都可以使用
db.executesql(string sql); db.executesql(string sql, object[] bindargs); //sql语句中使用占位符,然后第二个参数是实际的参数集
除了统一的形式之外,他们还有各自的操作方法:
db.insert(string table, string nullcolumnhack, contentvalues values); db.update(string table, contentvalues values, string whereclause, string whereargs); db.delete(string table, string whereclause, string whereargs);
以上三个方法的第一个参数都是表示要操作的表名;insert中的第二个参数表示如果插入的数据每一列都为空的话,需要指定此行中某一列的名称,系统将此列设置为null,不至于出现错误;insert中的第三个参数是contentvalues类型的变量,是键值对组成的map,key代表列名,value代表该列要插入的值;update的第二个参数也很类似,只不过它是更新该字段key为最新的value值,第三个参数whereclause表示where表达式,比如“age > ? and age < ?”等,最后的whereargs参数是占位符的实际参数值;delete方法的参数也是一样
下面给出demo
数据的添加
1.使用insert方法
contentvalues cv = new contentvalues();//实例化一个contentvalues用来装载待插入的数据 cv.put("title","you are beautiful");//添加title cv.put("weather","sun"); //添加weather cv.put("context","xxxx"); //添加context string publish = new simpledateformat("yyyy-mm-dd hh:mm:ss") .format(new date()); cv.put("publish ",publish); //添加publish db.insert("diary",null,cv);//执行插入操作
2.使用execsql方式来实现
string sql = "insert into user(username,password) values ('jack johnson','ilovepopmuisc');//插入操作的sql语句 db.execsql(sql);//执行sql语句
数据的删除
同样有2种方式可以实现
string whereclause = "username=?";//删除的条件 string[] whereargs = {"jack johnson"};//删除的条件参数 db.delete("user",whereclause,whereargs);//执行删除
使用execsql方式的实现
string sql = "delete from user where username='jack johnson'";//删除操作的sql语句 db.execsql(sql);//执行删除操作
数据修改
同上,仍是2种方式
contentvalues cv = new contentvalues();//实例化contentvalues cv.put("password","ihatepopmusic");//添加要更改的字段及内容 string whereclause = "username=?";//修改条件 string[] whereargs = {"jack johnson"};//修改条件的参数 db.update("user",cv,whereclause,whereargs);//执行修改
使用execsql方式的实现
string sql = "update user set password = 'ihatepopmusic' where username='jack johnson'";//修改的sql语句 db.execsql(sql);//执行修改
数据查询
下面来说说查询操作。查询操作相对于上面的几种操作要复杂些,因为我们经常要面对着各种各样的查询条件,所以系统也考虑到这种复杂性,为我们提供了较为丰富的查询形式:
db.rawquery(string sql, string[] selectionargs); db.query(string table, string[] columns, string selection, string[] selectionargs, string groupby, string having, string orderby); db.query(string table, string[] columns, string selection, string[] selectionargs, string groupby, string having, string orderby, string limit); db.query(string distinct, string table, string[] columns, string selection, string[] selectionargs, string groupby, string having, string orderby, string limit);
上面几种都是常用的查询方法,第一种最为简单,将所有的sql语句都组织到一个字符串中,使用占位符代替实际参数,selectionargs就是占位符实际参数集;
各参数说明:
table:表名称
colums:表示要查询的列所有名称集
selection:表示where之后的条件语句,可以使用占位符
selectionargs:条件语句的参数数组
groupby:指定分组的列名
having:指定分组条件,配合groupby使用
orderby:y指定排序的列名
limit:指定分页参数
distinct:指定“true”或“false”表示要不要过滤重复值
cursor:返回值,相当于结果集resultset
最后,他们同时返回一个cursor对象,代表数据集的游标,有点类似于javase中的resultset。下面是cursor对象的常用方法:
c.move(int offset); //以当前位置为参考,移动到指定行 c.movetofirst(); //移动到第一行 c.movetolast(); //移动到最后一行 c.movetoposition(int position); //移动到指定行 c.movetoprevious(); //移动到前一行 c.movetonext(); //移动到下一行 c.isfirst(); //是否指向第一条 c.islast(); //是否指向最后一条 c.isbeforefirst(); //是否指向第一条之前 c.isafterlast(); //是否指向最后一条之后 c.isnull(int columnindex); //指定列是否为空(列基数为0) c.isclosed(); //游标是否已关闭 c.getcount(); //总数据项数 c.getposition(); //返回当前游标所指向的行数 c.getcolumnindex(string columnname);//返回某列名对应的列索引值 c.getstring(int columnindex); //返回当前行指定列的值
实现代码
string[] params = {12345,123456}; cursor cursor = db.query("user",columns,"id=?",params,null,null,null);//查询并获得游标 if(cursor.movetofirst()){//判断游标是否为空 for(int i=0;i<cursor.getcount();i++){ cursor.move(i);//移动到指定记录 string username = cursor.getstring(cursor.getcolumnindex("username"); string password = cursor.getstring(cursor.getcolumnindex("password")); } }
通过rawquery实现的带参数查询
cursor result=db.rawquery("select id, name, inventory from mytable"); //cursor c = db.rawquery("s name, inventory from mytable where id=?",new stirng[]{"123456"}); 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();
在上面的代码示例中,已经用到了这几个常用方法中的一些,关于更多的信息,大家可以参考官方文档中的说明。
最后当我们完成了对数据库的操作后,记得调用sqlitedatabase的close()方法释放数据库连接,否则容易出现sqliteexception。
上面就是sqlite的基本应用,但在实际开发中,为了能够更好的管理和维护数据库,我们会封装一个继承自sqliteopenhelper类的数据库操作类,然后以这个类为基础,再封装我们的业务逻辑方法。
这里直接使用案例讲解:下面是案例demo的界面
sqliteopenhelper类介绍
sqliteopenhelper是sqlitedatabase的一个帮助类,用来管理数据库的创建和版本的更新。一般是建立一个类继承它,并实现它的oncreate和onupgrade方法。
方法名 | 方法描述 |
---|---|
sqliteopenhelper(context context,string name,sqlitedatabase.cursorfactory factory,int version) |
构造方法,其中 context 程序上下文环境 即:xxxactivity.this; name :数据库名字; factory:游标工厂,默认为null,即为使用默认工厂; version 数据库版本号 |
oncreate(sqlitedatabase db) | 创建数据库时调用 |
onupgrade(sqlitedatabase db,int oldversion , int newversion) | 版本更新时调用 |
getreadabledatabase() | 创建或打开一个只读数据库 |
getwritabledatabase() | 创建或打开一个读写数据库 |
首先创建数据库类
import android.content.context; import android.database.sqlite.sqlitedatabase; import android.database.sqlite.sqlitedatabase.cursorfactory; import android.database.sqlite.sqliteopenhelper; public class sqlitedbhelper extends sqliteopenhelper { // 步骤1:设置常数参量 private static final string database_name = "diary_db"; private static final int version = 1; private static final string table_name = "diary"; // 步骤2:重载构造方法 public sqlitedbhelper(context context) { super(context, database_name, null, version); } /* * 参数介绍:context 程序上下文环境 即:xxxactivity.this * name 数据库名字 * factory 接收数据,一般情况为null * version 数据库版本号 */ public sqlitedbhelper(context context, string name, cursorfactory factory, int version) { super(context, name, factory, version); } //数据库第一次被创建时,oncreate()会被调用 @override public void oncreate(sqlitedatabase db) { // 步骤3:数据库表的创建 string strsql = "create table " + table_name + "(tid integer primary key autoincrement,title varchar(20),weather varchar(10),context text,publish date)"; //步骤4:使用参数db,创建对象 db.execsql(strsql); } //数据库版本变化时,会调用onupgrade() @override public void onupgrade(sqlitedatabase arg0, int arg1, int arg2) { } }
正如上面所述,数据库第一次创建时oncreate方法会被调用,我们可以执行创建表的语句,当系统发现版本变化之后,会调用onupgrade方法,我们可以执行修改表结构等语句。
我们需要一个dao,来封装我们所有的业务方法,代码如下:
import android.content.context; import android.database.cursor; import android.database.sqlite.sqlitedatabase; import com.chinasoft.dbhelper.sqlitedbhelper; public class diarydao { private sqlitedbhelper sqlitedbhelper; private sqlitedatabase db; // 重写构造方法 public diarydao(context context) { this.sqlitedbhelper = new sqlitedbhelper(context); db = sqlitedbhelper.getwritabledatabase(); } // 读操作 public string execquery(final string strsql) { try { system.out.println("strsql>" + strsql); // cursor相当于jdbc中的resultset cursor cursor = db.rawquery(strsql, null); // 始终让cursor指向数据库表的第1行记录 cursor.movetofirst(); // 定义一个stringbuffer的对象,用于动态拼接字符串 stringbuffer sb = new stringbuffer(); // 循环游标,如果不是最后一项记录 while (!cursor.isafterlast()) { sb.append(cursor.getint(0) + "/" + cursor.getstring(1) + "/" + cursor.getstring(2) + "/" + cursor.getstring(3) + "/" + cursor.getstring(4)+"#"); //cursor游标移动 cursor.movetonext(); } db.close(); return sb.deletecharat(sb.length()-1).tostring(); } catch (runtimeexception e) { e.printstacktrace(); return null; } } // 写操作 public boolean execother(final string strsql) { db.begintransaction(); //开始事务 try { system.out.println("strsql" + strsql); db.execsql(strsql); db.settransactionsuccessful(); //设置事务成功完成 db.close(); return true; } catch (runtimeexception e) { e.printstacktrace(); return false; }finally { db.endtransaction(); //结束事务 } } }
我们在dao构造方法中实例化sqlitedbhelper并获取一个sqlitedatabase对象,作为整个应用的数据库实例;在增删改信息时,我们采用了事务处理,确保数据完整性;最后要注意释放数据库资源db.close(),这一个步骤在我们整个应用关闭时执行,这个环节容易被忘记,所以朋友们要注意。
我们获取数据库实例时使用了getwritabledatabase()方法,也许朋友们会有疑问,在getwritabledatabase()和getreadabledatabase()中,你为什么选择前者作为整个应用的数据库实例呢?在这里我想和大家着重分析一下这一点。
我们来看一下sqliteopenhelper中的getreadabledatabase()方法:
public synchronized sqlitedatabase getreadabledatabase() { if (mdatabase != null && mdatabase.isopen()) { // 如果发现mdatabase不为空并且已经打开则直接返回 return mdatabase; } if (misinitializing) { // 如果正在初始化则抛出异常 throw new illegalstateexception("getreadabledatabase called recursively"); } // 开始实例化数据库mdatabase try { // 注意这里是调用了getwritabledatabase()方法 return getwritabledatabase(); } catch (sqliteexception e) { if (mname == null) throw e; // can't open a temp database read-only! log.e(tag, "couldn't open " + mname + " for writing (will try read-only):", e); } // 如果无法以可读写模式打开数据库 则以只读方式打开 sqlitedatabase db = null; try { misinitializing = true; string path = mcontext.getdatabasepath(mname).getpath();// 获取数据库路径 // 以只读方式打开数据库 db = sqlitedatabase.opendatabase(path, mfactory, sqlitedatabase.open_readonly); if (db.getversion() != mnewversion) { throw new sqliteexception("can't upgrade read-only database from version " + db.getversion() + " to " + mnewversion + ": " + path); } onopen(db); log.w(tag, "opened " + mname + " in read-only mode"); mdatabase = db;// 为mdatabase指定新打开的数据库 return mdatabase;// 返回打开的数据库 } finally { misinitializing = false; if (db != null && db != mdatabase) db.close(); } }
在getreadabledatabase()方法中,首先判断是否已存在数据库实例并且是打开状态,如果是,则直接返回该实例,否则试图获取一个可读写模式的数据库实例,如果遇到磁盘空间已满等情况获取失败的话,再以只读模式打开数据库,获取数据库实例并返回,然后为mdatabase赋值为最新打开的数据库实例。既然有可能调用到getwritabledatabase()方法,我们就要看一下了:
public synchronized sqlitedatabase getwritabledatabase() { if (mdatabase != null && mdatabase.isopen() && !mdatabase.isreadonly()) { // 如果mdatabase不为空已打开并且不是只读模式 则返回该实例 return mdatabase; } if (misinitializing) { throw new illegalstateexception("getwritabledatabase called recursively"); } // if we have a read-only database open, someone could be using it // (though they shouldn't), which would cause a lock to be held on // the file, and our attempts to open the database read-write would // fail waiting for the file lock. to prevent that, we acquire the // lock on the read-only database, which shuts out other users. boolean success = false; sqlitedatabase db = null; // 如果mdatabase不为空则加锁 阻止其他的操作 if (mdatabase != null) mdatabase.lock(); try { misinitializing = true; if (mname == null) { db = sqlitedatabase.create(null); } else { // 打开或创建数据库 db = mcontext.openorcreatedatabase(mname, 0, mfactory); } // 获取数据库版本(如果刚创建的数据库,版本为0) int version = db.getversion(); // 比较版本(我们代码中的版本mnewversion为1) if (version != mnewversion) { db.begintransaction();// 开始事务 try { if (version == 0) { // 执行我们的oncreate方法 oncreate(db); } else { // 如果我们应用升级了mnewversion为2,而原版本为1则执行onupgrade方法 onupgrade(db, version, mnewversion); } db.setversion(mnewversion);// 设置最新版本 db.settransactionsuccessful();// 设置事务成功 } finally { db.endtransaction();// 结束事务 } } onopen(db); success = true; return db;// 返回可读写模式的数据库实例 } finally { misinitializing = false; if (success) { // 打开成功 if (mdatabase != null) { // 如果mdatabase有值则先关闭 try { mdatabase.close(); } catch (exception e) { } mdatabase.unlock();// 解锁 } mdatabase = db;// 赋值给mdatabase } else { // 打开失败的情况:解锁、关闭 if (mdatabase != null) mdatabase.unlock(); if (db != null) db.close(); } } }
大家可以看到,几个关键步骤是,首先判断mdatabase如果不为空已打开并不是只读模式则直接返回,否则如果mdatabase不为空则加锁,然后开始打开或创建数据库,比较版本,根据版本号来调用相应的方法,为数据库设置新版本号,最后释放旧的不为空的mdatabase并解锁,把新打开的数据库实例赋予mdatabase,并返回最新实例。
看完上面的过程之后,大家或许就清楚了许多,如果不是在遇到磁盘空间已满等情况,getreadabledatabase()一般都会返回和getwritabledatabase()一样的数据库实例,所以我们在dbmanager构造方法中使用getwritabledatabase()获取整个应用所使用的数据库实例是可行的。当然如果你真的担心这种情况会发生,那么你可以先用getwritabledatabase()获取数据实例,如果遇到异常,再试图用getreadabledatabase()获取实例,当然这个时候你获取的实例只能读不能写了
最后,让我们看一下如何使用这些数据操作方法来显示数据,界面核心逻辑代码:
public class sqliteactivity extends activity { public diarydao diarydao; //因为getwritabledatabase内部调用了mcontext.openorcreatedatabase(mname, 0, mfactory); //所以要确保context已初始化,我们可以把实例化dao的步骤放在activity的oncreate里 @override protected void oncreate(bundle savedinstancestate) { diarydao = new diarydao(sqliteactivity.this); initdatabase(); } class viewocl implements view.onclicklistener { @override public void onclick(view v) { string strsql; boolean flag; string message; switch (v.getid()) { case r.id.btnadd: string title = txttitle.gettext().tostring().trim(); string weather = txtweather.gettext().tostring().trim();; string context = txtcontext.gettext().tostring().trim();; string publish = new simpledateformat("yyyy-mm-dd hh:mm:ss") .format(new date()); // 动态组件sql语句 strsql = "insert into diary values(null,'" + title + "','" + weather + "','" + context + "','" + publish + "')"; flag = diarydao.execother(strsql); //返回信息 message = flag?"添加成功":"添加失败"; toast.maketext(getapplicationcontext(), message, toast.length_long).show(); break; case r.id.btndelete: strsql = "delete from diary where tid = 1"; flag = diarydao.execother(strsql); //返回信息 message = flag?"删除成功":"删除失败"; toast.maketext(getapplicationcontext(), message, toast.length_long).show(); break; case r.id.btnquery: strsql = "select * from diary order by publish desc"; string data = diarydao.execquery(strsql); toast.maketext(getapplicationcontext(), data, toast.length_long).show(); break; case r.id.btnupdate: strsql = "update diary set title = '测试标题1-1' where tid = 1"; flag = diarydao.execother(strsql); //返回信息 message = flag?"更新成功":"更新失败"; toast.maketext(getapplicationcontext(), message, toast.length_long).show(); break; } } } private void initdatabase() { // 创建数据库对象 sqlitedbhelper sqlitedbhelper = new sqlitedbhelper(sqliteactivity.this); sqlitedbhelper.getwritabledatabase(); system.out.println("数据库创建成功"); } }
android sqlite3数据库管理工具
android sdk的tools目录下提供了一个sqlite3.exe工具,这是一个简单的sqlite数据库管理工具。开发者可以方便的使用其对sqlite数据库进行命令行的操作。
程序运行生成的*.db文件一般位于"/data/data/项目名(包括所处包名)/databases/*.db",因此要对数据库文件进行操作需要先找到数据库文件:
1、进入shell 命令
adb shell
2、找到数据库文件
#cd data/data
#ls --列出所有项目
#cd project_name --进入所需项目名
#cd databases
#ls --列出现寸的数据库文件
3、进入数据库
#sqlite3 test_db --进入所需数据库
会出现类似如下字样:
sqlite version 3.6.22
enter ".help" for instructions
enter sql statements terminated with a ";"
sqlite>
至此,可对数据库进行sql操作。
4、sqlite常用命令
>.databases --产看当前数据库
>.tables --查看当前数据库中的表
>.help --sqlite3帮助
>.schema --各个表的生成语句
希望本文所述对大家android程序设计有所帮助。