首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用错误代码14 SQLITE_CANTOPEN:无法打开数据库清除存储后的应用程序崩溃

使用错误代码14 SQLITE_CANTOPEN:无法打开数据库清除存储后的应用程序崩溃
EN

Stack Overflow用户
提问于 2019-07-17 19:01:47
回答 1查看 339关注 0票数 1

清除应用程序存储和缓存后,开始收到未知错误(代码14 SQLITE_CANTOPEN):无法打开数据库。在清理存储器之前,所有东西都正常工作,无论是模拟器还是设备。

我试着从仿真器、擦除模拟器和清理项目中删除应用程序,但在打开MainActivity时仍然崩溃。为了解决问题,我在AndroidManifest中添加了写入权限,但仍然存在相同的错误。

代码语言:javascript
运行
复制
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

而不是做

代码语言:javascript
运行
复制
this.baza_putanja = "/data/data/" + context.getPackageName() + "/" + "databases/";

我做到了

代码语言:javascript
运行
复制
baza_putanja = context.getDatabasePath(baza_ime).getPath();

让我困扰的是,如果我试图使用不包括数据库名称的路径打开数据库--为什么在清除应用程序存储和缓存之前它是工作的?

BazaPodatakaHelper.java

代码语言:javascript
运行
复制
    private String baza_putanja = null;
    private static final String baza_ime = "eng_dictionary.db";
    private SQLiteDatabase econDictionary;
    private final Context mContext;

    public BazaPodatakaHelper(Context context) {
        super(context, baza_ime, null, 1);
        this.mContext = context;
        this.baza_putanja = "/data/data/" + context.getPackageName() + "/" + "databases/";
        Log.e("Putanja 1", baza_putanja);
    }

public void kreirajBazuPodataka() throws IOException {

        boolean bazaPodatakaPostoji = provjeriBazuPodataka();
        if ( !bazaPodatakaPostoji ) {
            this.getReadableDatabase();
            try {
                kopirajBazuPodataka();
            } catch (IOException e) {
                throw new Error("Greška prilikom kopiranja baze podataka");
            }
        }
    }

public boolean provjeriBazuPodataka() {

        SQLiteDatabase provjera;

        try {
            String putanja = baza_putanja + baza_ime;
            provjera = SQLiteDatabase.openDatabase(putanja, null, SQLiteDatabase.OPEN_READONLY);
        } catch (SQLiteException e) {
            throw new Error("Greška prilikom provjeravanja baze podataka");
        }

        if (provjera != null) {
            provjera.close();
        }

        return provjera != null;
    }

错误日志:

代码语言:javascript
运行
复制
2019-07-17 20:39:30.482 7885-7885/com.benjaminkljn.econdictionary E/Putanja 1: /data/data/com.benjaminkljn.econdictionary/assets/ 2019-07-17 20:39:30.485 7885-7885/com.benjaminkljn.econdictionary E/SQLiteLog: (14) cannot open file at line 36683 of [c255889bd9] 2019-07-17 20:39:30.485 7885-7885/com.benjaminkljn.econdictionary E/SQLiteLog: (14) os_unix.c:36683: (2) open(/data/data/com.benjaminkljn.econdictionary/assets/eng_dictionary.db)
-  2019-07-17 20:39:30.491 7885-7885/com.benjaminkljn.econdictionary E/SQLiteDatabase: Failed to open database '/data/data/com.benjaminkljn.econdictionary/assets/eng_dictionary.db'.
    android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14 SQLITE_CANTOPEN): Could not open database
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-18 00:06:44

信息是说

代码语言:javascript
运行
复制
/data/data/com.benjaminkljn.econdictionary/assets/eng_dictionary.db

上面的代码不包括路径中的,所以您的问题可能就是基于这一点的。

通常,特别是,如果使用context.getDatabasePath(your_database),则尝试打开

代码语言:javascript
运行
复制
/data/data/com.benjaminkljn.econdictionary/databases/eng_dictionary.db
  • 数据库文件夹,而不是资产

此外,在你的评论中你提到:-

代码语言:javascript
运行
复制
>I've deleted and re-imported database

通常情况下,导入数据库(至少是为应用程序导入数据库)会将要导入的数据库(包括在应用程序中)复制到assets文件夹中。

因此,您可能试图从您认为是资产文件夹的地方打开数据库,但是您不能直接使用包含/导入的资产文件夹,因为资产是由AssetsManager.管理的。

您可能可以使用设备资源管理器在/data/data/com.benjaminkljn.econ字典中创建资产文件夹,然后将数据库复制到该文件夹中,然后打开该文件夹即可工作。

如果您以前这样做了,那么在删除/卸载App之后,如果数据库没有手动复制到资产文件夹(因此已经创建了资产文件夹),则会导致您遇到的问题。

  • 安装应用程序时,将创建/data/data/com.benjaminkljn.econ字典文件夹,但不创建子文件夹数据库而不是名为assets的子文件夹,清除应用程序的存储将有效地恢复到这一点。

但是,手动复制数据库,只适用于特定的应用程序。如果发布了该应用程序,它将无法工作,因为您无法手动复制该文件。

若要在应用程序中使用预先存在的数据库,建议的方法是:

  1. 创建应用程序或应用程序的一部分
  2. 在main/src/中创建资产文件夹(与res/java文件夹和android.manaifest所在的位置相同)。
    1. 注意到如果使用SQLiteAssetHelper,则在assets文件夹中创建数据库文件夹。

  1. 将数据库复制到资产
  2. 然后,在尝试使用数据库之前,应用程序应该将数据库从资产文件夹中复制,并使用AssetManager访问数据库,然后将其复制到数据库将被访问的位置。
    1. 通常这个位置是/data/data/the_package_name/databases/your_database
    2. 确定位置的可靠/推荐方法是使用context.getDatabasePath(your_database)。
    3. 注意,数据库文件夹将不存在于一个新的应用程序,必须创建(SQLiteAssethelper将这样做)。

SQliteAssethelper简化了这一点。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57082591

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档