当前位置: 首页 > 知识库问答 >
问题:

False SQLite错误?代码14

狄阳秋
2023-03-14

我遇到了一个奇怪的问题。我正在查询数据库表中的单词列表,并能够获得该列表。但是我无法更新该表。奇怪的是,logcat显示Code 14错误。我卸载了应用程序,重新运行它,所以数据库是新复制的,但是什么都没有改变。

以下是dbHandler代码:

public VocabDatabase(Context context) {

    super(context, DB_NAME, null, 1);
    this.myContext = context;
    this.DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
}

/**
 * Creates a empty database on the system and rewrites it with your own database.
 */
public void createDataBase() throws IOException {

    boolean dbExist = checkDataBase();

    if (dbExist) {
        //do nothing - database already exist
    } else {
        //By calling this method and empty database will be created into the default system path
        //of your application so we are gonna be able to overwrite that database with our database.
        this.getWritableDatabase();

        try {
            copyDataBase();
        } catch (IOException e) {
            throw new Error("Error copying database");

        }

    }

}

/**
 * Check if the database already exist to avoid re-copying the file each time you open the application.
 *
 * @return true if it exists, false if it doesn't
 */
private boolean checkDataBase() {
    this.getReadableDatabase();

    SQLiteDatabase checkDB = null;

    try {
        String myPath = DB_PATH;
        checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);

    } catch (SQLiteException e) {
        e.printStackTrace();
    }

    if (checkDB != null) {

        checkDB.close();

    }

    return (checkDB != null) ? true : false;
}
private boolean checkDataBaseAlt(){
    File chkdb = new File(DB_PATH);
    return chkdb.exists();
}

/**
 * Copies your database from your local assets-folder to the just created empty database in the
 * system folder, from where it can be accessed and handled.
 * This is done by transfering bytestream.
 */
private void copyDataBase() throws IOException {

    //Open your local db as the input stream
    InputStream myInput = myContext.getAssets().open(DB_NAME);

    // Path to the just created empty db
    String outFileName = DB_PATH + DB_NAME;

    //Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    //transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length = 0;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }

    //Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();

}

public void openDataBase() throws SQLException {

    //Open the database
    String myPath = DB_PATH + DB_NAME;
    myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);

}

@Override
public synchronized void close() {

    if (myDataBase != null)
        myDataBase.close();

    super.close();

}

@Override
public void onCreate(SQLiteDatabase db) {

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (newVersion > oldVersion) {
        try {
            copyDataBase();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

// Add your public helper methods to access and get content from the database.
// You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
// to you to create adapters for your views.

//add your public methods for insert, get, delete and update data in database.

public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy);
}

public long insert(String table, String nullColumnHack, ContentValues contentValues) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.insert(table, nullColumnHack, contentValues);
}

public Cursor rawQuery(String string, String[] selectionArguments) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.rawQuery(string, selectionArguments);
}
public long update(String table, ContentValues contentValues, String whereClause, String[] whereArgs) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.update(table, contentValues, whereClause, whereArgs);
}

}

这是服务代码:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    vdb = new VocabDatabase(this);
    Toast.makeText(this, "Service started", Toast.LENGTH_SHORT).show();
    createDB();
    queryDB();
    return super.onStartCommand(intent, flags, startId);
}
private void createDB() {
    vdb.getWritableDatabase();
    try {
        vdb.createDataBase();
        vdb.openDataBase();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public void queryDB() {
    String vet = "";
    ArrayList<String> lister = new ArrayList<>();
    Cursor cr = vdb.query(TABLE_NAME, null, null, null, null, null, null);
if (cr.moveToFirst()) {
        do {
            lister.add(cr.getString(0));
        } while (cr.moveToNext());
    }
cr.close();
String vet="";
for (String v : lister) {
            vet += v + "\t";
        }
}

字符串兽医显示在烤面包中,我可以看到表格第一列中的所有单词。但是我无法更新行。

private void updateInDatabase(String up, String pot) {
    ContentValues conval = new ContentValues();
    conval.put(pot, "1");
    try {
        long res = vdb.update(TABLE_NAME, conval, "Word=?", new String[]{up});
    } catch (Exception e) {

    }
}

我已经给了它存储权限,并对其进行了双重检查。

清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.hack.corrector">
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service android:name=".scrapeservice"/>
</application>

错误日志:

05-17 13:39:04.614 28088-28088/com.example.hack.corrector E/SQLiteLog: (14) cannot open file at line 31282 of [5a3022e081]
05-17 13:39:04.615 28088-28088/com.example.hack.corrector E/SQLiteLog: (14) os_unix.c:31282: (21) open(/data/user/0/com.example.hack.corrector/databases/) - 
05-17 13:39:04.616 28088-28088/com.example.hack.corrector E/SQLiteDatabase: Failed to open database '/data/user/0/com.example.hack.corrector/databases/'.
    android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
        at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:207)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:191)
        at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
        at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:806)
        at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:791)
        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
        at com.example.hakc.corrector.VocabDatabase.checkDataBase(VocabDatabase.java:81)
        at com.example.hakc.corrector.VocabDatabase.createDataBase(VocabDatabase.java:48)
        at com.example.hakc.corrector.scrapeservice.createDB(scrapeservice.java:48)
        at com.example.hakc.corrector.scrapeservice.onStartCommand(scrapeservice.java:39)
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3049)
        at android.app.ActivityThread.access$2300(ActivityThread.java:154)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1479)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:157)
        at android.app.ActivityThread.main(ActivityThread.java:5571)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:635)
05-17 1

共有3个答案

呼延河
2023-03-14

我相信您会发现,无法打开数据库错误实际上不是故障,而是问题的迹象。这就是checkdataBase方法遇到的打开错误,因为它无法按消息所述打开数据库。由于它被捕获,因此不会导致故障。

相反,所发生的是,checkDatabase方法返回false,因为它无法打开数据库,因此每次运行应用程序时都会从资产中复制数据库。从而撤消以前运行的任何更改。

使用两行代码诊断/调试这一点很简单。

  1. 通过添加日志。d(“DBEXISTCHK”,“方法checkdataBase returned”String.valueOf(dbExist))

根据:-

/**
 * Creates a empty database on the system and rewrites it with your own database.
 */
public void createDataBase() throws IOException {

    boolean dbExist = checkDataBase();
    Log.d("DBEXISTCHK", "Method checkdataBase returned" + String.valueOf(dbExist)); //<<<<<<<<<< ADDED

    if (dbExist) {
        //do nothing - database already exist
    } else {
        //By calling this method and empty database will be created into the default system path
        //of your application so we are gonna be able to overwrite that database with our database.
        this.getWritableDatabase();
        try {
            copyDataBase();
        } catch (IOException e) {
            throw new Error("Error copying database");
        }
    }
}

根据:-

private void copyDataBase() throws IOException {

    Log.d("DBCOPY","Database is being copied from the Assets."); //<<<<<<<<<< ADDED

    //Open your local db as the input stream
    InputStream myInput = myContext.getAssets().open(DB_NAME);

    // Path to the just created empty db
    String outFileName = DB_PATH + DB_NAME;

    //Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    //transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length = 0;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }

    //Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();

}

结果日志将类似于(注意最后两行):-

05-17 10:12:22.591 1152-1152/bcdbfa.basiccopydbfromassets E/SQLiteLog: (14) cannot open file at line 30174 of [00bb9c9ce4]
    (14) os_unix.c:30174: (21) open(/data/data/bcdbfa.basiccopydbfromassets/databases/) - 
05-17 10:12:22.591 1152-1152/bcdbfa.basiccopydbfromassets E/SQLiteDatabase: Failed to open database '/data/data/bcdbfa.basiccopydbfromassets/databases/'.
    android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
        at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
        at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
        at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
        at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
        at bcdbfa.basiccopydbfromassets.VocabDatabase.checkDataBase(VocabDatabase.java:85)
        at bcdbfa.basiccopydbfromassets.VocabDatabase.createDataBase(VocabDatabase.java:45)
        at bcdbfa.basiccopydbfromassets.MainActivity.onCreate(MainActivity.java:18)
        at android.app.Activity.performCreate(Activity.java:5008)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
        at android.app.ActivityThread.access$600(ActivityThread.java:130)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4745)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
        at dalvik.system.NativeStart.main(Native Method)
05-17 10:12:22.591 1152-1152/bcdbfa.basiccopydbfromassets W/System.err: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
        at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
        at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
        at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
        at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
05-17 10:12:22.599 1152-1152/bcdbfa.basiccopydbfromassets W/System.err:     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
        at bcdbfa.basiccopydbfromassets.VocabDatabase.checkDataBase(VocabDatabase.java:85)
        at bcdbfa.basiccopydbfromassets.VocabDatabase.createDataBase(VocabDatabase.java:45)
        at bcdbfa.basiccopydbfromassets.MainActivity.onCreate(MainActivity.java:18)
        at android.app.Activity.performCreate(Activity.java:5008)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
        at android.app.ActivityThread.access$600(ActivityThread.java:130)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4745)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
        at dalvik.system.NativeStart.main(Native Method)
05-17 10:12:22.599 1152-1152/bcdbfa.basiccopydbfromassets D/DBEXISTCHK: Method checkdataBase returnedfalse
05-17 10:12:22.599 1152-1152/bcdbfa.basiccopydbfromassets D/DBCOPY: Database is being copied from the Assets.

修复更简单,这只是一个改变的问题:-

    String myPath = DB_PATH;

    String myPath = DB_PATH + DB_NAME;

checkDatabase方法中。

在这种情况下,日志中的结果(如果保留日志)将为:-

05-17 10:30:49.809 1265-1265/? D/DBEXISTCHK: Method checkdataBase returnedtrue

仅创建同名的空数据库。

这是因为在调用createDatabase方法之前,您正在createDB方法中调用getWritableDatabase。也就是说,如果没有数据库,getWritableDatabase将创建一个空数据库(禁止sqlite_master表,对于android,禁止android_metadata表),然后调用onCreate方法。这就解释了为什么当完整路径正确时,会绕过数据库的副本,并且因此存在数据库空数据库。

但是当我把“myPath”改回myPath=DB\u Path时;整个数据库都被复制了,但问题仍然存在。

如前所述,当路径不正确时,checkDatabase方法将始终返回false,因此调用copyDatabase方法,因为使用的路径正确。

所以

private void createDB() {
    vdb.getWritableDatabase(); //<<<<<<<<<< The villainous line
    try {
        vdb.createDataBase();
        vdb.openDataBase();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

应该是

private void createDB() {
    try {
        vdb.createDataBase();
        vdb.openDataBase();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

显然,所有路径都是包含数据库名称的完整路径。

宋高谊
2023-03-14

就像例外告诉我们的:

无法打开数据库/data/user/0/com.example.hack.corrector/databases/。

您正试图使用变量DB\u PATH打开SQLite DB,如下所示

this.DB_PATH = context.getApplicationInfo().dataDir + "/databases/";

您不设置文件名,只设置目录路径<代码>数据库//code>是一个目录。

将文件名设置为您的路径:

this.DB_PATH = context.getApplicationInfo().dataDir + "/databases/my_db";

编辑:您有两个DB名称变量。。。您正在使用DB\u NAME打开与助手的连接(在超级构造函数中),然后在您使用的检查方法中。

因此,您可以从助手获得连接

this.getWritableDatabase(); //Using the DB at `DB_NAME`

但Will没能联系上

String myPath = DB_PATH;
SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);

因为您使用了DB_PATH而不是DB_NAME。您使用了2个不同的数据库路径。

端木朝
2023-03-14

如果您在API级别23或更高版本上运行应用程序,则会出现此问题,因为本文引入了新的实时权限模型。在这些版本中,用户在应用运行时向应用授予权限

为了在运行时获得权限,您必须请求用户。您可以通过以下方式完成:

请求权限

String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions, REQUEST_CODE); //REQUEST_CODE can be any Integer value

并检查您的权限结果

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
       case REQUEST_CODE:
         if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
           //Permission granted.
           //Now you can try your database creating and writing stuff.

         }
       else{
           //Permission denied.
         }
        break;
    }
}

如果这不能解决您的问题,请转到此链接。对于同一个问题,这里有许多解决方案。

Android数据库sqlite。SqliteContoPenDatabaseException:未知错误(代码14):无法打开数据库

 类似资料:
  • 错误代码 宏定义 #define  RT_EOK   0   无错误   #define  RT_ERROR   1   一般错误   #define  RT_ETIMEOUT   2   超时错误   #define  RT_EFULL   3   资源已满   #define  RT_EEMPTY   4   资源已空   #define  RT_ENOMEM   5   内存不足   #de

  • 说明:编写一条if语句,验证字符串是否包含字符。 添加一个if语句,检查是否大于零。不要忘记if语句末尾的!如果字符串中确实有一些字符,则打印用户的单词。否则(即:语句),请打印空。您需要多次运行代码,测试空字符串和带字符的字符串。当你确信你的代码可以工作时,继续下一个练习。 我被卡住了,因为我一直遇到以下错误。我做错了什么?

  • 我的服务器上的Https不工作并得到。我尝试了太多的东西,但无法得到任何结果。我的带有Nginx反向代理的HttpSpring启动服务器工作得很好。 下面是我的 /etc/nginx/conf.d/*. conf文件: 我已经检查了我的443端口是否打开并正在监听。 我不知道我哪里做错了任何帮助都将感激不尽

  • 1005:创建表失败 1006:创建数据库失败 1007:数据库已存在,创建数据库失败 1008:数据库不存在,删除数据库失败 1009:不能删除数据库文件导致删除数据库失败 1010:不能删除数据目录导致删除数据库失败 1011:删除数据库文件失败 1012:不能读取系统表中的记录 1020:记录已被其他用户修改 1021:硬盘剩余空间不足,请加大硬盘可用空间 1022:关键字重复,更改记录失败

  • public static final int ERROR_CODE_SUCCESS = -1; public static final int ERROR_CODE_INTERNAL_ERROR = 0; public static final int ERROR_CODE_INVALID_REQUEST = 1; public static final int ERROR_CODE_NETWO

  • 问题内容: 我有桌子 当我尝试运行此查询时: 错误代码:1292。第1行“ data_apertura”列的日期值错误:“ 01-05-2012” * 我要改变什么?(我试图将格式的日期从gg / mm / yyyy更改为gg-mm-yyyy,但未进行任何更改) 问题答案: 以以下格式示例插入日期,