我知道这是一个重复的问题,但是堆栈溢出中的旧问题对我没有帮助,因为情况已经改变。
a)我已将我的 SQLite 文件your.db
复制到中的 asset 文件夹(只读)中Android Studio
b)在我的应用中,我已通过以下方式将资产从资产复制到内部存储空间:
// Internal Storage Path: (/Data/User/0/*myapppath*/files)
val name="your.db"
val f = this.assets.open(name)
val SQLContent = f.bufferedReader().use{ it.readText()}
f.close()
val file = File(this.filesDir, name)
file.writeText(SQLContent)
c)我已经检查过我的文件是否确实复制到了 Android 手机中
以下代码显示在按钮上显示OK
。是的。
val file = File(this.filesDir, "your.db")
if (file.exists()) result="Ok" else result="Argh"I
d)下面的代码用于打开我的数据库(已存储在内部存储器中)。但是,由于系统找不到我的数据库,因此出现错误。
String DBPath = file.getabsolutePath()
SQLiteDatabase db = SQLiteDatabase.openDatabase(DBPath,
null, SQLiteDatabase.OPEN_READWRITE)
我知道推荐的 SQLite 数据库位置是...\databases
而不是...\files
,但是即使那样,给出错误也没有意义,因为文件实际上是在那里。
更新:
使用@commonsware注释,我使用了设备文件资源管理器。因此,我注意到SQLiteDatabase.openDatabase
在文件名中放置了corrupt
前缀,但是,错误是
Error Code : 1294 (SQLITE_CANTOPEN_ENOENT)
Caused By : Specified directory or database file does not exist.
(unknown error (code 1294): Could not open database)
更新2
使用@commonsware接受的答案,我替换了用于复制二进制版本文件的代码。
将文件从资产复制到内部存储空间
val arq = this.assets.open(nome)
val file = File(this.filesDir, nome)
val saida = file.outputStream()
arq.copyTo(saida)
saida.close()
arq.close()
现在,它可以正常运行。我打开SQLite,使用游标运行查询,扫描游标,打印记录,关闭游标并关闭数据库。没有其他错误。
使用设备文件资源管理器工具(菜单 View ,工具Windows )时,它将显示私有应用程序文件。当我将SQLite文件复制回我的计算机时(在右侧按钮上下文菜单中使用copy as
)在复制期间仍然失败。我认为此选项尝试将文件复制为文本而不是二进制文件。
答案 0 :(得分:3)
我没有注意到您在编辑中添加了文件复制代码。
val SQLContent = f.bufferedReader().use{ it.readText()}
SQLite数据库是二进制文件,而不是文本。使用readBytes()
和writeBytes()
,而不是readText()
和writeText()
。
答案 1 :(得分:1)
资产始终是R / O,因为它们是APK文件的一部分。这是Java中的示例方法,该方法返回一个R / W句柄(其中DATABASE_FILENAME
是要打开的文件名):
private static SQLiteDatabase db;
private Context mContext;
@Nullable
public SQLiteDatabase getDatabase() {
/* attempting to return early */
if(db != null && db.isOpen()) {
return db;
} else {
SQLiteDatabase db = null;
File path = this.mContext.getDatabasePath(Constants.DATABASE_FILENAME);
if (path.exists()) {
try {
db = SQLiteDatabase.openDatabase(path.getAbsolutePath(), null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteCantOpenDatabaseException e) {
Log.e(LOG_TAG, e.getMessage());
}
} else {
Log.e(LOG_TAG, path.getAbsolutePath() + " does not exist.");
}
return db;
}
}
(普通),期望的数据库目录为/databases
,而不是/files
。并且,如果打算从资产中打开R / O(例如,从资产中导入),则必须标记OPEN_READONLY
...这可能是SQLITE_CANTOPEN_ENOENT
与标记{ {1}}和R / O资源;两次调用OPEN_READWRITE
也是导入数据时要考虑的问题。我只使用db.close()
来插入...,这是搞乱数据库文件的可靠选择-甚至可以插入本地化的字符串。二进制副本在内容本地化方面严重失败。