在运行时,位于 assets 文件夹中的 SQLite 引发了异常。
在运行时,位于 assets 文件夹中的 SQLite 引发了异常。
在尝试加载我的Android数据库文件时,我遇到了以下异常:
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.jk.sqlite_test, PID: 32660 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.jk.sqlite_test/com.example.jk.sqlite_test.MainActivity}: com.readystatesoftware.sqliteasset.SQLiteAssetHelper$SQLiteAssetException: Missing databases/Data.db file (or .zip, .gz archive) in assets, or target folder not writable at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2493) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2576) at android.app.ActivityThread.access$1000(ActivityThread.java:155) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5539) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: com.readystatesoftware.sqliteasset.SQLiteAssetHelper$SQLiteAssetException: Missing databases/Data.db file (or .zip, .gz archive) in assets, or target folder not writable at android.content.res.AssetManager.openAsset(Native Method) at android.content.res.AssetManager.open(AssetManager.java:313) at android.content.res.AssetManager.open(AssetManager.java:287) at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.copyDatabaseFromAssets(SQLiteAssetHelper.java:436) at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.createOrOpenDatabase(SQLiteAssetHelper.java:400) at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getWritableDatabase(SQLiteAssetHelper.java:176) at com.example.jk.sqlite_test.DatabaseAccess.open(DatabaseAccess.java:28) at com.example.jk.sqlite_test.MainActivity.onCreate(MainActivity.java:25) at android.app.Activity.performCreate(Activity.java:6289) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2446) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2576) at android.app.ActivityThread.access$1000(ActivityThread.java:155) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5539) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) D/AppTracker: App Event: crash
以下是我的代码:
package com.example.jk.sqlite_test; import android.content.Context; import com.readystatesoftware.sqliteasset.SQLiteAssetHelper; public class DatabaseOpenHelper extends SQLiteAssetHelper { private static final String DATABASE_NAME = "Data.db"; private static final int DATABASE_VERSION = 3; public DatabaseOpenHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } }
还有:
package com.example.jk.sqlite_test; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import java.util.ArrayList; public class DatabaseAccess { private SQLiteOpenHelper openHelper; private SQLiteDatabase database; private static DatabaseAccess instance; private DatabaseAccess(Context context) { this.openHelper = new DatabaseOpenHelper(context); } public static DatabaseAccess getInstance(Context context) { if (instance == null) { instance = new DatabaseAccess(context); } return instance; } public void open() { this.database = openHelper.getWritableDatabase(); } public void close() { if (database != null) { this.database.close(); } } public String getAll() { String str = ""; Cursor cursor = database.rawQuery("SELECT * FROM pdata" , null); cursor.moveToFirst(); while(!cursor.isAfterLast()) { str += cursor.getString(1) + "\t" + cursor.getString(2) + "\t" + cursor.getString(3) + "\n"; } return str; } }
我猜我在使用SQLite 3数据库,所以将版本设置为3。
在SQLite Studio中创建数据库文件后,我没有得到任何文件扩展名,所以我将扩展名保持为db,正如许多相似问题的答案中建议的那样。
我还尝试使用不同的版本值和扩展名,如.sqlite/.sqlite3,但没有解决这个问题。
请帮忙!
谢谢。
在上述代码中,问题出现在尝试从assets文件夹中复制SQLite数据库文件到应用程序的数据库文件夹时。问题的原因是在运行时,出现了一个异常。
解决这个问题的方法是确保数据库文件正确地复制到正确的文件夹中。可以通过以下步骤来解决这个问题:
1. 检查数据库文件是否已存在,可以使用checkDataBase()方法来实现。如果数据库文件已存在,则不需要复制。
2. 如果数据库文件不存在,则需要复制数据库文件。可以使用copyDataBase()方法来实现。在该方法中,首先调用getReadableDatabase()方法,然后关闭数据库,最后使用InputStream和OutputStream从assets文件夹中读取和写入数据库文件。
3. 在copyDBFile()方法中,打开assets文件夹中的数据库文件,然后将其写入到应用程序的数据库文件夹中。
4. 在DatabaseHelper类的构造函数中,通过调用copyDataBase()方法来复制数据库文件。然后调用getReadableDatabase()方法,以确保数据库已正确创建。
5. 最后,在close()方法中,关闭数据库连接。
通过按照上述步骤来解决问题,可以确保在运行时不会出现异常,从而成功复制SQLite数据库文件到应用程序的数据库文件夹中。
问题的原因是:SQLiteOpenHelper要求数据库文件必须放在assets/databases文件夹中,而不是assets文件夹中。解决方法是创建一个databases文件夹,并将Data.db文件复制到该文件夹中。
另外,代码中的getAll方法存在问题,如果使用该方法并且至少有一行数据,则会进入无限循环,因为在while循环中调用了movetoFirst方法,但没有调用moveToNext方法。建议修改getAll方法如下:
public String getAll() { String str = ""; Cursor cursor = database.rawQuery("SELECT * FROM pdata" , null); while(cursor.moveToNext()) { str += cursor.getString(1) + "\t" + cursor.getString(2) + "\t" + cursor.getString(3) + "\n"; } return str; }
此外,还有一个问题是在Android Studio中创建数据库文件是无效的,需要在SQLite工具中创建文件,然后将保存的文件复制到assets/databases文件夹中,文件名和数据库名必须相同。
最后,如果遇到问题仍无法解决,可以参考Stack Overflow上的一个回答。
问题的出现原因是尝试在只读模式的文件夹(assets)中以写入模式打开数据库。解决方法是尝试以只读模式打开数据库,使用openHelper.getReadableDatabase()
。
好的,你是对的,现在异常已经消失了,但是出现了一个新的异常,错误信息是:"Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database"。
请检查数据库的位置。它是在/assets/databases/Data.db还是在/assets/Data.db中?再提一个建议:避免使用大写字母,将资源的名称设置为小写,并用下划线分隔。