转载请注明出处。谢谢:http://blog.csdn.net/harryweasley/article/details/46467495

我们都知道,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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSGFycnlXZWFzbGV5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">


网上非常多介绍,我这里不介绍。

2.假设是真机。首先这个真机是root过了。下载一个Root Explorer。

我的測试机是华为荣耀3c。

当我们运行完了以上的步骤后。进入data/data/jz.his.jzhis/databases/会看到这种情景。

事实上lgx就是我们刚刚创建的数据库,lgx-journal是数据库日志。

如今我们知道了,数据库存储的位置了,你以为这就是我写这篇博客的目的?继续往下看吧,嘿嘿。

假设我不想再手机系统内存中保存数据库,而是想将我的数据库放在手机sd卡中。那应该怎么做呢。

首先,我在res/raw中放一个现成的数据库。待会在代码里,将它拷入手机sd卡中。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSGFycnlXZWFzbGV5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

看以下的代码:

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当运行总结的更多相关文章

  1. 由sqlite在手机上的存储位置,引发的onCreate在哪里执行的小结

    我们都知道,android为了操作数据库,一般是继承SQLiteOpenHelper类,并实现他的三个函数. 如下所示: package jz.his.db; import android.conte ...

  2. SQLite剖析之动态内存分配

    SQLite通过动态内存分配来获取各种对象(例如数据库连接和SQL预处理语句)所需内存.建立数据库文件的内存Cache.保存查询结果. 1.特性    SQLite内核和它的内存分配子系统提供以下特性 ...

  3. 错误信息:内存位置访问无效。 (Exception from HRESULT: 0x800703E6)

    错误提示: 错误信息:内存位置访问无效. (Exception from HRESULT: 0x800703E6) 异常类型:System.BadImageFormatException 堆栈跟踪: ...

  4. system v和posix的共享内存对比 & 共享内存位置

    参考 http://www.startos.com/linux/tips/2011012822078.html 1)Linux和所有的UNIX操作系统都允许通过共享内存在应用程序之间共享存储空间. 2 ...

  5. Android开发之定义app在手机的安装位置

    定义app在手机的安装位置,可以通过在清单文件中添加属性 android:installLocation="" 该属性有三个值:auto(自动),preferExternal(外部 ...

  6. Android 获取手机总内存和可用内存等信息

    在android开发中,有时候我们想获取手机的一些硬件信息,比如android手机的总内存和可用内存大小.这个该如何实现呢? 通过读取文件"/proc/meminfo"的信息能够获 ...

  7. Java中字符串内存位置浅析

    前言 之前写过一篇关于JVM内存区域划分的文章,但是昨天接到蚂蚁金服的面试,问到JVM相关的内容,解释一下JVM的内存区域划分,这部分答得还不错,但是后来又问了Java里面String存放的位置,之前 ...

  8. 你好,C++(15)四两拨千斤——3.9 指向内存位置的指针

    3.9  指向内存位置的指针 一天,两个变量在街上遇到了: “老兄,你家住哪儿啊?改天找你玩儿去.” “哦,我家在静态存储区的0x0049A024号,你家呢?” “我家在动态存储区的0x0022FF0 ...

  9. 如何在 Windows Phone 8 中获取手机的当前位置

    原文 如何在 Windows Phone 8 中获取手机的当前位置 适用于:仅限于 Windows Phone 8. 本主题演示如何使用 Windows Phone 位置 API 确定手机的当前位置. ...

随机推荐

  1. Python pip 安装包

    Python 第三方包可以使用pip 更容易地安装,和管理 pip 的下载地址 https://pypi.python.org/pypi/pip/ pip的使用以及相关文档参考 https://pip ...

  2. [置顶] oracle 数据库表中转换成java代码

    --数据库中字段java代码 select col.TABLE_NAME,replace(initcap(col.TABLE_NAME),'_', '')   , 'private '||decode ...

  3. 爬虫总结_java

    基于webmagic的爬虫项目经验小结 大概在1个月前,利用webmagic做了一个爬虫项目,下面是该项目的一些个人心得,贴在这里备份: 一.为什么选择webmagic? 说实话,开源的爬虫框架已经很 ...

  4. [计算机基础]URI与URL

    URI : uniform resource identifier统一资源标示符用于指定Web资源的字符串,它定义了Web资源中的各个不同的部分.ex:http://example.org/absol ...

  5. jquery的ajax提交form表单方式总结

    方法一: function AddHandlingFeeToRefund() { var AjaxURL= "../OrderManagement/AjaxModifyOrderServic ...

  6. 求刷Kindle Fire HD的方法

    前几天入手了台Amazon Kindle Fire HD 其系统是经过Amazon尝试改造过的Android,用起来很不爽,想刷个CM10之类的,求教程和工具.

  7. 怎样从ext3升级到ext4?

    Ext4 文件系统提供了更佳的性能和可靠性,具有了更为丰富的功能,那么,怎样从ext3升级到ext4呢? 首先,我们须要保证系统支持ext4,一般来说,内核版本号在2.6.28及以上的版本号才支持ex ...

  8. ADO面板上的控件简介

    ADO面板上的控件简介 一. TADOConnection组件该组件用于建立数据库的连接.ADO的数据源组件和命令组件可以通过该组件运行命令及数据库中提取数据等.该组件用于建立数据库的连接,该连接可被 ...

  9. HDU 1007 近期点对

    分治法求近期点对 递归将点不断分成小组.计算最短距离.此时的最短距离不过两点都属两块的某一块(这里的切割点是mid点). 还须要考虑两点分属两块的情况. 这时对于选点则把范围缩小到了以mid为中心. ...

  10. 硬盘重装Ubuntu12.04的感受

    好久没更blog了,最近这两天系统也出了问题,win7蓝屏,ubuntu进不去-.后来win7整好了,ubuntu依旧顽固.用惯了linux,就不想在转到win7下面了,估计是习惯了各种敲命令的感觉吧 ...