转载请注明出处,谢谢: 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);}@Overridepublic 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)");}@Overridepublic 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">MessageDataBasemessageDataBase = 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,则没有数据库,返回falsereturn 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这个方法,才会在系统内存有数据库。


折磨了我一个下午啊啊啊啊。



更多相关文章

  1. IntentService使用、原理
  2. Android(安卓)app开发中获取cpu arm架构信息及执行shell命令方法
  3. Android(安卓)java.lang.NoClassDefFoundError的一种解决方法
  4. 深入理解ActivityManagerService,你知道的不知道的全在这里!
  5. Android(安卓)Mqtt重连的一个小问题
  6. 蓝牙hid协议源码解析
  7. Flutter ubuntu 环境搭建
  8. Android(安卓)Studio连接不上模拟器的解决方法
  9. 如何解决向eclipse导入android project时遇到错误“Invalid proj

随机推荐

  1. Android(安卓)Manifest.xml全局配置文件
  2. Android(安卓)HIDL第一个HelloWorld demo
  3. android下远程GDB调试
  4. Android,谁动了我的内存
  5. Android中的资源分析
  6. Android适合手机开发的又一力证——安卓
  7. Android开发者必知的开发资源
  8. Android(安卓)GIF 编解码
  9. 【如何在不同Android设备中得到有效的Aud
  10. Android高手进阶教程(二十三)之---Androi