Android Sqlite 数据库复制数据库函数路径

Android Sqlite Database copyDatabase function Paths

我正在使用下面的代码复制 sqlite 数据库,只是想知道路径的正确编码是什么,因为 Android Studio 建议不要对路径进行硬编码,如附图所示。这里的大多数答案也使用硬编码 /data/data 路径。

    companion object {

    private val DATABASE_VERSION = 1
    private val DATABASE_NAME = "books.db"

    @JvmStatic
    fun copyDatabase(context: Context) {

        LogUtil.loge("copyDatabase")
        try {
            var dir = "/data/data/" + context.getPackageName() + "/databases"
            if (Build.VERSION.SDK_INT >= 24){
                dir = context.dataDir.absolutePath + "/databases/"
            }
            if(!File(dir).exists()){
                LogUtil.loge("databases dir not exist")
                File(dir).mkdir()
            }
            val outFileName = context.getDatabasePath(DATABASE_NAME)
            val myOutput = FileOutputStream(outFileName)
            val buffer = ByteArray(1024)
            var length: Int
            val myInput = context.assets.open("databases/$DATABASE_NAME")
            length = myInput.read(buffer)
            while (length > 0) {
                myOutput.write(buffer, 0, length)
                length = myInput.read(buffer)
            }
            myInput.close()
            myOutput.flush()
            myOutput.close()
        } catch (e: IOException) {
            e.printStackTrace()
            LogUtil.loge("unable to copy database")
        }
    }
}

最初使用Context的getDatabasePath("databasename");创建一个File对象,然后使用File的getParentFile获取目录作为文件然后作为OutputStream的基础。您需要做的就是硬编码数据库名称(以及资产文件夹中的数据库文件夹)。

getDatabasePath

例如像 :-

private fun dbcopy(context: Context) {

    val dbfile = File(context.getDatabasePath(DATABASE_NAME).path)
    if (!dbfile.parentFile.exists()) {
        dbfile.parentFile.mkdirs()
    }
    try {
        val os = FileOutputStream(dbfile)
        // and so on
    } catch (e: IOException) {

    }

}

P.S。无需检查版本,以上适用于我知道的所有版本(尽管是从 Java 转换而来)。

您需要在打开资产时对 数据库 进行硬编码,因为它不是 standard/pre-defined/must 使用文件夹。

我倾向于进行目录检查和创建,作为检查数据库是否存在的一部分,例如:-

private fun checkDataBase(context: Context): Boolean {

    val db = File(context.getDatabasePath(DATABASE_NAME).path) //Get the file name of the database
    if (db.exists()) return true // If it exists then return doing nothing

    val dbdir = db.parentFile
    // If the directory does not exist then make the directory (and higher level directories)
    if (!dbdir.exists()) {
        db.parentFile.mkdirs()
        dbdir.mkdirs()
    }
    return false
}

以下是一个完整的帮助程序(少了任何访问数据库的方法),如果数据库不存在,它将从资产数据库文件夹中复制数据库:-

class MyDBHelper(internal var myContext: Context) : SQLiteOpenHelper(myContext, DATABASE_NAME, null, DATABASE_VERSION) {
    internal var buffer_size = 1024 * 4

    init {
        if (!checkDataBase()) {
            copyDataBase()
        }
    }

    override fun onCreate(db: SQLiteDatabase) {}

    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {}

    private fun checkDataBase(): Boolean {

        val db = File(myContext.getDatabasePath(DATABASE_NAME).path) //Get the file name of the database
        Log.d("DBPATH", "DB Path is " + db.path) //TODO remove for Live App
        if (db.exists()) return true // If it exists then return doing nothing

        // Get the parent (directory in which the database file would be)
        val dbdir = db.parentFile
        // If the directory does not exits then make the directory (and higher level directories)
        if (!dbdir.exists()) {
            db.parentFile.mkdirs()
            dbdir.mkdirs()
        }
        return false
    }

    private fun copyDataBase() {
        try {

            val myInput = myContext.assets.open("databases" + File.separator + DATABASE_NAME) // Open the Asset file
            val outfile = File(myContext.getDatabasePath(DATABASE_NAME).toString())
            val myOutput = FileOutputStream(outfile)
            //transfer bytes from the inputfile to the outputfile
            val buffer = ByteArray(buffer_size)
            var length = myInput.read(buffer)
            while (length > 0) {
                myOutput.write(buffer, 0, length)
                length = myInput.read(buffer)
            }
            //Close the streams
            myOutput.flush()
            myOutput.close()
            myInput.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    companion object {
        private val DATABASE_NAME = "thedatabase.db"
        private val DATABASE_VERSION = 1
    }
}
  • 请注意,文件分隔符不是硬编码,而是根据系统值获取的。