解决SQLite打开已有路径下的db问题

最近遇到的需要加载已有路径下(sd card下)db的问题,找了一下资料,以下是解决的方法,仅供参考(转载自eoe):

SQLiteOpenHelper 是Android框架为我们提供的一个非常好的数据库打开、升级与关闭的工具类。但是这个工具类会自动把db文件创建到“ /data/data/com.*.*(package name)/” 目录下,这么做可能是与Android文件系统的设计思路有关。

但 是在实战过程中,我们可能有各种原因需要自定义db文件路径(例如db文件较大放到sd卡更安全等等),相信很多人都遇到了这个需求,网上也有很多解决方 法,这些方法大多是抛弃Android框架为我们提供的SQLiteOpenHelper类,自己重头写一个DbHelper类完成自定义路径的数据库打 开关闭等。这么做虽然可以解决问题,但并不是一个最好的方法,因为自己写的DbHelper可靠性和功能自然难和google巨匠相。

本文提出一种方法,通过继承和添加代码,并复用SQLiteOpenHelper的代码,来解决自定义db路径的问题。


先我们来分析一下SQLiteOpenHelper的源代码。getReadableDatabase()和getWritableDatabase()
在内部都是调用getDatabaseLocked()。getDatabaseLocked()的源代码很容易理解,分析得知:

  • 如果以只读方式打开,是通过mContext.getDatabasePath(mName)来获取db文件的路径并使用SQLiteDatabase.openDatabase()直接打开数据库;

  • 果以读写方式打开,是通过mContext.openOrCreateDatabase(mName,
    mEnableWriteAheadLogging ? Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
    mFactory, mErrorHandler)打开或创建数据库。

所以我们需要改变mContext的行为。Android框架提供了一个ContextWrapper类,是Context的一个代理,可以通过继承的方式拉改变Context的行为,所以我们继承ContextWrapper,代码如下:

class CustomPathDatabaseContext extends ContextWrapper{
    private String mDirPath;

  public CustomPathDatabaseContext(Context base, String dirPath) {

    super(base);

    this.mDirPath = dirPath;

  }

  @Override

  public File getDatabasePath(String name) {

    File result = new File(mDirPath + File.separator + name);

    if (!result.getParentFile().exists()){

      result.getParentFile().mkdirs();

    }

    return result;

    }

    

  @Override

  public SQLiteDatabase openOrCreateDatabase(String name, int mode ,CursorFactory factory){

    return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);

  }

  

  @Override

  public SQLiteDatabase openOrCreateDatabase(String name,
int mode, CursorFactory factory, DatabaseErrorHandler errorHandler){

    return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name).getAbsolutePath(),
factory, errorHandler);

  }
  }

上述代码很简单了,就不用多说明了吧,然后我们在继承SQLiteOpenHelper时这么写就可以了:

class YourDbHelper extends SQLiteOpenHelper{

public YourDbHelper(Context context, String name, CursorFactory factory,
                        int version) {
                super(new CustomPathDatabaseContext(context, getDirPath()), name, factory, version);
        }

/**
         * 获取db文件在sd卡的路径
         * @return
         */
        private static String getDirPath(){
                //TODO 这里返回存放db的文件夹的绝对路径
                return "";
        }
        
        @Override
        public void onCreate(SQLiteDatabase db) {
        }

@Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }
        
  }

如此一来,我们既可以自定义db文件路径,又可以复用SQLiteOpenHelper十分好用的功能了~

另外需要注意的是,有些应
用可能是有一个已建好表的db文件放在assets中,应用运行时先判断db文件是否存在,如果不存在则从assets中复制到自定义路径。这种情况通常
都是在PC端使用SQLiteSpy诸如此类的工具写sql建表,使用这种方法的小伙伴们别忘了在建表时执行  PRAGMA
schema_version = 1   这句sql(当然了版本号取决于您的需求) ,
否则SQLiteOpenHelper还是会触发onCreate的~看了SQLiteOpenHelper什么时候触发onCreate的源码就明白怎么回事了~

时间: 2024-10-01 22:05:11

解决SQLite打开已有路径下的db问题的相关文章

关于myeclipse10.6安装路径下没有common这个目录的解决方法

大家都知道myeclipse10.6破解就是找Myeclipse下的Common\plugins目录进行替换文件,从而破解! 一般情况下,common这个目录就在安装myeclipse的安装目录下,但特殊情况喜爱不在安装目录下: 原因可能如下: 安装时文件夹没有访问权限,导致在安装目录下写不进Common\plugins目录 myeclipse官方故意进行影藏,以防用户进行对此文件的修改: 解决方法如下: 对第一种情况,安装是右击安装包,点"以管理员身份运行". 安装后找安装目录看是否

Ubuntu在任一路径下打开终端

sudo apt-get install nautilus-open-terminal 安装完毕之后即可在任一路径下打开终端了:

将盘mount到已存在路径,路径下文件显示不了

添加盘: Disk /dev/sdb: 1073 MB, 1073741824 bytes 255 heads, 63 sectors/track, 130 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk ide

如何使用eclipse打开已有工程

在开始使用Eclipse的时候,会发现一个问题,那就是如何打开一个现有的Eclipse工程,开始在菜单中找了好久也没找到. 其实,Eclipse生成的结果不像VC,Jcreator那样可以直接打开,若要打开非workspace文件夹下的其他已有工程,可以打开菜单file->import→general→existing project into space.在select root directory中选中要打开的文件夹即可.此时如果选择copy existing project into wo

打开已存在 Android项目及常见的问题

Eclipse 打开已存在 Android项目及常见的问题 1.  点击菜单"File"-- "Import",会弹出 Import 对话框: Android项目及常见的问题" name="image_operate_84841359866226255" alt="打开已存在 Android项目及常见的问题" src="http://s6.sinaimg.cn/mw690/93dc666cgd4ca6e4e

解决Sqlite Developer过期的最简单办法(转自百度经验)

第一种方法是:打开注册表  开始-->运行-->输入regedit 依次打开目录:HKEY_CURRENT_USER\SharpPlus\SqliteDev 找到右侧的StartDate项,删除. 第二种方法更简单,开始--> 运行 -->cmd,或者是window+R组合键,调出命令窗口 复制:reg delete "HKEY_CURRENT_USER\SharpPlus\SqliteDev" /v "StartDate" /f 粘贴到窗口

(转贴)|DataDirectory|解决webconfig数据库连接的相对路径问题

webconfig中的数据库连接是不支持Server.MapPath的,一般我们只能写上数据库文件的物理路径,这给网站迁移带来很大的不方便.今天在网上找到了一个解决办法,与大家分享下.看以下代码: <connectionStrings> <add name="ConnStr_Access" providerName="System.Data.OleDb" connectionString="Provider=Microsoft.Jet.O

C#遍历指定路径下的文件夹

通过指定路径访问路径下的文件,在C#的开发中主要利用了Directory类和DirectoryInfo类,简要介绍Directory类中的成员:命名空间 System.IO 命名空间 1.CreateDirectory,已重载,用于创建指定路径下的所有目录: 2.Delete,删除指定目录: 3.Exists,确定给定目录是否引用磁盘现有目录:说白点就是判断路径是否存在: 4.GetCreationTime,获取目录的创建时间和日期: 4.GetCurrentDirectory,获取应用程序的当

Mac版Python打开文件的路径问题

原文地址:https://www.jianshu.com/p/b8110d578155 1.文件路径选择 mac不存在地址栏,有时候你去获取文件路径粘贴过来打开会报错 File b'***.csv' does not exist 而你不想每次要去找数据文件路径,最简单的办法是先获取你在编辑的Ipython notebook的路径,然后把数据文件放在该路径下,到时候直接输入文件名就能打开文件了. #获取默认路径 import os print (os.path.abspath('.')) 比如我的