Android Kotlin导入预置数据库到Room报SQLite损坏错误怎么解决?
错误原因
从日志里的Invalid MagicHeader、file is not a database报错可以判断是SQLite无法识别导入的数据库文件,常见原因如下:
- 你放在assets目录下的
loadData.db不是合法的SQLite数据库文件:很多开发者会直接把SQL脚本修改后缀为.db就当成数据库文件使用,这种文件没有SQLite的标准文件头,会直接触发损坏报错。 - 预置数据库文件被构建工具压缩:Android打包时默认会压缩assets下的部分类型文件,压缩后的数据库文件会破坏原有结构,无法被SQLite识别。
- 预置数据库版本和Room声明的版本不匹配:你代码中Room的数据库版本为15,如果你预置的
loadData.db的user_version值和15不一致,也会触发异常。 - 你提供的建表SQL存在语法错误:
restaurant_table的location字段定义末尾多了一个多余的逗号,直接执行该SQL会建表失败,生成的数据库文件本身就存在问题。
解决方案
- 生成合法的预置数据库文件
不要直接将SQL脚本改后缀为.db,你需要先通过SQLite可视化工具(如DB Browser for SQLite、SQLiteStudio)执行修正后的SQL语句,确认数据库、表、数据都正常生成后,将导出的.db文件放到assets/databases目录下。 - 禁止构建工具压缩数据库文件
在app模块的build.gradle中添加如下配置,避免.db文件被压缩:
如果使用KTS格式的gradle配置,写法如下:android { aaptOptions { noCompress 'db' } }android { aaptOptions { noCompress.add("db") } } - 统一预置数据库和Room的版本
在生成预置数据库时,执行如下SQL语句将数据库版本设置为和Room声明的15一致:PRAGMA user_version = 15; - 修正建表SQL的语法错误
删除location字段末尾多余的逗号,修正后的建表语句如下:CREATE TABLE IF NOT EXISTS "restaurant_table" ( "restaurantId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "restaurant_name" TEXT NOT NULL, "phone_number" TEXT NOT NULL, "Category" TEXT NOT NULL, "location" TEXT NOT NULL ); - 清理旧缓存
修改完成后先卸载设备上的旧应用,删除之前生成的损坏的本地数据库文件,再重新安装测试。
内容的提问来源于stack exchange,提问作者pepperlove
相关产品推荐
相关产品推荐

