由sqlite在手机上的存储位置,引发的onCreate在哪里执行的小结
我们都知道,android为了操作数据库,一般是继承SQLiteOpenHelper类,并实现他的三个函数。
如下所示:
package jz.his.db; import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper; public class MessageDataBase extends SQLiteOpenHelper { public MessageDataBase(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table lgx_table(_id integer primary key autoincrement ," +
"name varchar(20),content varchar(40),time varchar(20) ,head varchar(20),isCheck byte)");
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
} }
</pre><p>可以看到创建了一个名为lgx_table的表,里面有一id,name,content等列。</p><p></p>然后在Activity里,通过getWritableDatabase或者getReadableDatabase()方法来实例化一个SQLiteDatabase<p></p><p></p><pre name="code" class="java">MessageDataBase messageDataBase = new MessageDataBase(context, "lgx", null, 1);
SQLiteDatabase database = messageDataBase.getWritableDatabase();
我们可以看到,创建了一个名字为“lgx”的数据库。
这里提出一个问题,通过以上的步骤后,数据库保存在哪里了呢?
数据库保存在data/data/[your packageName]/databses,
1.如果是模拟器,直接通过Eclipse下,通过这样的步骤去看 DBMS--->File Explorer-->data---->data--->your packageName

网上很多介绍,我这里不介绍。
2.如果是真机,首先这个真机是root过了,下载一个Root Explorer。我的测试机是华为荣耀3c。
当我们执行完了以上的步骤后,进入data/data/jz.his.jzhis/databases/会看到这样的情景。

其实lgx就是我们刚刚创建的数据库,lgx-journal是数据库日志。
现在我们知道了,数据库存储的位置了,你以为这就是我写这篇博客的目的?继续往下看吧,嘿嘿。
如果我不想再手机系统内存中保存数据库,而是想将我的数据库放在手机sd卡中,那应该怎么做呢。
首先,我在res/raw中放一个现成的数据库,待会在代码里,将它拷入手机sd卡中。

看下面的代码:
package com.example.province; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment; public class CopyOfCityInfoDataSupport2 {
private static CopyOfCityInfoDataSupport2 cityInfoDataSupport;
/**
* 数据库在手机里的路径
*/
private static String DATABASE_PATH = Environment
.getExternalStorageDirectory() + "/aaaaa/";
/**
* 数据库的名称
*/
public static final String dbName = "mzk_db";
private SQLiteDatabase mSDB; public static CopyOfCityInfoDataSupport2 getInstance(Context context) {
initDataBase(context);
if (cityInfoDataSupport == null) {
cityInfoDataSupport = new CopyOfCityInfoDataSupport2();
}
return cityInfoDataSupport; } /**
* 初试化数据库
*/
private static void initDataBase(Context context) {
boolean dbExist = checkDataBase();
if (dbExist) { } else {
// 如果不存在,则将raw里的数据存入手机sd卡
copyDataBase(context);
}
} /**
* 复制数据库到手机指定文件夹下
*
* @throws IOException
*/
private static void copyDataBase(Context context) {
String databaseFilenames = DATABASE_PATH + dbName;
File dir = new File(DATABASE_PATH);
FileOutputStream os = null;
InputStream is = null;
// 判断文件夹是否存在,不存在就创建一个
if (!dir.exists()) {
dir.mkdirs();
}
try {
// 得到数据库的输出流
os = new FileOutputStream(databaseFilenames);
// 得到数据文件的输入流
is = context.getResources().openRawResource(R.raw.mzk_db);
byte[] buffer = new byte[8192];
int count = 0;
while ((count = is.read(buffer)) != -1) {
os.write(buffer, 0, count);
os.flush();
}
// 之所以不在这里初始化,是因为这边是静态的方法,而mSDB并没有设置为静态的,也不推荐设为静态的
// mSDB = SQLiteDatabase.openOrCreateDatabase(DATABASE_PATH +
// dbName, null);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
} } } /**
* 判断数据库是否存在
*
* @return
*/
private static boolean checkDataBase() {
SQLiteDatabase checkDB = null;
String databaseFilename = DATABASE_PATH + dbName;
// 要自己加上try catch方法
try {
// 返回最新的数据库
checkDB = SQLiteDatabase.openDatabase(databaseFilename, null,
SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
// TODO: handle exception
} if (checkDB != null) {
checkDB.close();
}
// 如果checkDB为null,则没有数据库,返回false
return checkDB == null ? false : true;
} /**
* 查询所有省份的信息
*
* @return 省份信息
*/
public ArrayList<City> queryProvince() {
// 创建数据库的实例
mSDB = SQLiteDatabase
.openOrCreateDatabase(DATABASE_PATH + dbName, null);
ArrayList<City> list = new ArrayList<City>();
String sql = "select * from fs_province";
Cursor cursor = mSDB.rawQuery(sql, null);
while (cursor.moveToNext()) {
City city = new City();
String id = cursor.getString(cursor.getColumnIndex("ProvinceID"));
String name = cursor.getString(cursor
.getColumnIndex("ProvinceName"));
city.setName(name);
city.setId(id);
list.add(city);
}
if (cursor != null) {
cursor.close();
}
return list;
} public void closeDataBase() {
if (mSDB != null) {
mSDB.close();
}
}
}
我们看到,如果将数据库写到手机sd卡中,都不需要SQLiteOpenHelper类了,而是直接通过
mSDB = SQLiteDatabase.openOrCreateDatabase(DATABASE_PATH + dbName, null);就可以获得数据库的实例了。
但是这个方法有个缺点,就是不能进行数据库的升级了。显然这样是非常不好的。
那么如果我们还想用SQLiteOpenHelper,又将其写到sd卡中,又该怎么做呢。
下面的这段代码是有错误的,你只需要注意看51行,正是因为下面的代码,我才研究了onCreate方法到底什么时候执行。
package jz.his.db; import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List; import jz.his.jzhis.R;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
import android.util.Log; public class CityInfoDataSupport extends SQLiteOpenHelper
{
private final static String TAG = "CityInfoDataSupport";
public static final String dbName = "cityego";
// 数据库在手机里的路径
private static String DATABASE_PATH = Environment
.getExternalStorageDirectory().getAbsolutePath()+"/com.bcinfo.pwzs/";
private static int version = 1;
private final String GEOCODING_TABLE_NAME = "GEOCODING";
private SQLiteDatabase mSDB = getReadableDatabase();
private static CityInfoDataSupport mDataSupport;
Context context; public static CityInfoDataSupport getInstance(Context context)
{
initDatabse(context); if (mDataSupport == null)
{
mDataSupport = new CityInfoDataSupport(context);
}
return mDataSupport;
} CityInfoDataSupport(Context context)
{ super(context, DATABASE_PATH+dbName, null, version);
} @Override
public void onCreate(SQLiteDatabase db)
{
executeAssetsSQL(db, "geocoding_create.sql");
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
String sql = "drop table if exits " + GEOCODING_TABLE_NAME;
db.execSQL(sql);
onCreate(db);
} private void loadSql(SQLiteDatabase db, String schemaName)
{
InputStream inputS;
try
{
inputS = context.getAssets().open(schemaName);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputS));
String sql = null;
while ((sql = reader.readLine()) != null)
{
db.execSQL(sql.replace(";", ""));
}
reader.close();
reader = null;
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
} /**
* 读取数据库文件(.sql),并执行sql语句
* */
private void executeAssetsSQL(SQLiteDatabase db, String schemaName)
{
Log.e("DataSupport", "executeAssetsSQL");
BufferedReader in = null;
try
{
in = new BufferedReader(new InputStreamReader(context.getAssets().open(schemaName)));
String line;
String buffer = "";
while ((line = in.readLine()) != null)
{
buffer += line;
if (line.trim().endsWith(";"))
{
db.execSQL(buffer.replace(";", ""));
buffer = "";
}
}
}
catch (IOException e)
{
Log.e("db-error", e.toString());
}
finally
{
try
{
if (in != null)
in.close();
}
catch (IOException e)
{
Log.e("db-error", e.toString());
}
}
} public synchronized void insertCityInfo()
{
loadSql(mSDB, "geocoding_data.txt");
} public synchronized List<City> queryDataById(String field, String id)
{
String sql = "";
List<City> cityList = new ArrayList<City>();
if (field.equals("grade"))
{
sql = "select * from " + GEOCODING_TABLE_NAME + " where grade = ? ";
}
else if (field.equals("parent"))
{
sql = "select * from " + GEOCODING_TABLE_NAME + " where parent = ? ";
}
String[] params = new String[]
{ id };
Cursor c = mSDB.rawQuery(sql, params);
while (c.moveToNext())
{
City city = new City();
city.setGbCode(c.getString(c.getColumnIndex("gbcode")));
city.setGbName(c.getString(c.getColumnIndex("gbname")));
city.setGrade(c.getString(c.getColumnIndex("grade")));
city.setLongitude(c.getString(c.getColumnIndex("longtitude")));
city.setLatitude(c.getString(c.getColumnIndex("latitude")));
city.setParent(c.getString(c.getColumnIndex("parent")));
cityList.add(city);
}
if (c != null)
{
c.close();
}
return cityList;
} public void deleteAppTempTraffic()
{
String sql = "delete from " + GEOCODING_TABLE_NAME;
mSDB.execSQL(sql);
} public static void initDatabse(Context cntext)
{
boolean dbExist = checkDataBase();
//判断数据库是否存在 不存在就把raw里的数据库写入手机
if (!dbExist)
{
try
{
copyDataBase(cntext);
}
catch (IOException e)
{
throw new Error("Error copying database");
}
}
} /**
* 判断数据库是否存在
* @return false or true
*/
public static boolean checkDataBase()
{
SQLiteDatabase checkDB = null;
try
{
String databaseFilename = DATABASE_PATH + dbName;
checkDB = SQLiteDatabase.openDatabase(databaseFilename, null, SQLiteDatabase.OPEN_READONLY);
}
catch (SQLiteException e)
{
}
if (checkDB != null)
{
checkDB.close();
}
return checkDB != null ? true : false;
} /**
* 复制数据库到手机指定文件夹下
* @throws IOException
*/
public static void copyDataBase(Context context) throws IOException
{
String databaseFilenames = DATABASE_PATH + dbName;
File dir = new File(DATABASE_PATH);
FileOutputStream os = null;
// 判断文件夹是否存在,不存在就新建一个
if (!dir.exists())
{
dir.mkdirs();
}
try
{
// 得到数据库文件的写入流
os = new FileOutputStream(databaseFilenames);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
// 得到数据库文件的数据流
InputStream is = context.getResources().openRawResource(R.raw.cityego);
byte[] buffer = new byte[8192];
int count = 0;
try
{
while ((count = is.read(buffer)) > 0)
{
os.write(buffer, 0, count);
os.flush();
}
}
catch (IOException e)
{
}
try
{
is.close();
os.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
通过上面的这个代码,我的onCreate方法一直没有执行。最终经过我多次试验,我知道了问题所在,所以在这里进行总结。
那么onCreate方法到底什么时候执行呢?
SQLiteOpenHelper的onCreate方法一定是在getReadableDatabase方法之后的
SQLiteDatabase mSDB = getReadableDatabase()这个方法首先检查手机中,是否有已经存在的数据库,如果没有,则执行onCreate方法,如果有,则不执行---->但是,这里有个前提是,你的supre(context, DATABASE_PATH+dbName, null, version),的第二个参数不能是已存在的数据库路径。
我这里,将第二个参数,弄成了已存在的数据库文件,所以onCreate方法永远不会执行。
那么当super(context, dbName, null, version);第二个参数正确和并且执行了getReadableDatabase这个方法,才会在系统内存有数据库。
折磨了我一个下午啊啊啊啊。
由sqlite在手机上的存储位置,引发的onCreate在哪里执行的小结的更多相关文章
- docker - 修改镜像/容器文件的在宿主机上的存储位置(转)
背景 之前在使用docker的时候,由于启动container的时候用的是默认的mount(路径为 /var/lib/docker),这个目录对应的硬盘空间有限,只有200G左右.现在随着程序运行,有 ...
- docker - 修改镜像/容器文件或者 "Docker root dir" 的在宿主机上的存储位置
背景 之前在使用docker的时候,由于启动container的时候用的是默认的mount(路径为 /var/lib/docker),这个目录对应的硬盘空间有限,只有200G左右.现在随着程序运行,有 ...
- 由sqlite在手机的内存位置,引起onCreate当运行总结
转载请注明出处.谢谢:http://blog.csdn.net/harryweasley/article/details/46467495 我们都知道,android为了操作数据库,通常是继承SQLi ...
- Vue 在手机上键盘把底部菜单顶上去的解决方案
Vue 在手机上键盘把底部菜单顶上去的解决方案 ios和安卓的键盘的区别 ios和安卓的键盘的区别弹起方式不同, ios直接弹出键盘, 不影响页面, 而安卓键盘弹起时会把页面顶起来, 这样就会把底部菜 ...
- fastclick与zepto的 tap事件关于在手机上click事件的300ms延迟的区别
之前翻译过一篇关于fastclick的快速点击文章http://www.cnblogs.com/lilyimage/p/3568773.html,fastclick可以解决在手机上点击事件的300ms ...
- 如何正确地在手机上显示图片——QImage与QPixmap完全解析
引言 用Qt程序在手机上显示一幅图片对编程人员来说是再基础不过的一件事情了.那么先让大家看两段代码: //dangerous should not be used, cannot display ea ...
- 构建安全的Xml Web Service系列之wse之证书存储位置
原文:构建安全的Xml Web Service系列之wse之证书存储位置 我们在前几天对xml web service的安全性提出了一些建议,大家可以通过以下地址访问: 构建安全的Xml Web Se ...
- 可以在手机上看电脑本地html步骤,我自己总结的哦!
1.打开控制面板 2.打开程序和功能 3.打开或关闭功能 4.internet信息服务展开后里面所有的都要选中 5.回到桌面,然后右键计算机,选择'管理' 6.先在E盘或者D盘创建一个文件夹,自己随意 ...
- ubuntu14.04 rabbitmq安装与使用 --修改RabbitMQ数据存储位置
参考:https://blog.csdn.net/tianjiewang/article/details/58383062 说明: ubuntu14.04 rabiitmq 默认 安装路径 /va ...
随机推荐
- java 类名.class、object.getClass()和Class.forName()的区别 精析
1.介绍 getClass()介绍 java是面向对象语言,即万物皆对象,所有的对象都直接或间接继承自Object类: Object类中有getClass()方法,通过这个方法就可以获得一个实 ...
- Hive之简单查询不启用MapReduce
假设你想查询某个表的某一列.Hive默认是会启用MapReduce Job来完毕这个任务,例如以下: 01 hive> SELECT id, money FROM m limit 10; 02 ...
- [Done]SnowFlake 分布式环境下基于ZK构WorkId
Twitter 的 Snowflake 大家应该都熟悉的,先上个图: 时间戳 序列号一般不会去改造,主要是工作机器id,大家会进行相关改造,我厂对工作机器进行了如下改造(估计大家都差不多吧,囧~~~ ...
- SSO之CAS + LDAP
本来主要详细是介绍CAS和LDAP整合实现单点登录的步骤. 1. 依<SSO之安装CAS Server>所述安装好CAS Server.2. 安装ApacheDS.安装好ApacheDS后 ...
- My Sql 高效分页
/* *普通分页 *在数据文件上偏移1000000查出10条 */ select * from zoldesk_92game_net_ecms_bj where classid=303 ORDER B ...
- Tomcat路径下目录的介绍
本文转自:http://blog.csdn.net/u013132035/article/details/54949593 下图是TOMCAT的路径下目录的截图. 目录有:backup. ...
- [转]TCP(HTTP)长连接和短连接区别和怎样维护长连接
原文链接 一.HTTP协议和TCP协议 HTTP的长连接和短连接本质上是TCP长连接和短连接.HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议.IP协议主要解决网络路由和寻址问题, ...
- 百度定位SDK实现获取当前经纬度及位置
使用Android自带的LocationManager和Location获取位置的时候,经常会有获取的location为null的情况,并且操作起来也不是很方便,在这个Demo里我使用了百度地图API ...
- python学习笔记011——内置函数pow()
1 语法 pow(x, y[, z]) x -- 数值表达式. y -- 数值表达式. z -- 数值表达式. 函数是计算 x 的 y 次方,如果 z 在存在,则再对结果进行取模,其结果等效于pow( ...
- asp.net core mvc视频A:笔记3-7.ViewStart与ViewImort
项目位置 放在其它目录应该不会执行! 默认配置 默认配置