转载请注明出处,谢谢: http://www.jb51.cc/article/p-xwhhaoli-bgq.html
我们都知道,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,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();
这里提出一个问题,通过以上的步骤后,数据库保存在哪里了呢?
数据库保存在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,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,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();
- }
- }
- }
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,version);
- }
- @Override
- public void onCreate(sqliteDatabase db)
- {
- executeAssetssql(db,"geocoding_create.sql");
- }
- @Override
- public void onUpgrade(sqliteDatabase db,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,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,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,version),的第二个参数不能是已存在的数据库路径。
我这里,将第二个参数,弄成了已存在的数据库文件,所以onCreate方法永远不会执行。
那么当super(context,dbName,version);第二个参数正确和并且执行了getReadableDatabase这个方法,才会在系统内存有数据库。
折磨了我一个下午啊啊啊啊。