代码14:无法打开数据库 [英] Code 14: Unable to open database

查看:328
本文介绍了代码14:无法打开数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题曾经被问过。但是,问题是,相同的代码(用于数据库处理程序)适用于另一个应用程序,但不适用于我当前正在使用的应用程序。我什至通过检查设置中的权限来确保已授予权限。这是logcat:

I know this question has been asked before. But, the problem is, the same code (for database handler) is working for another app, but not the one I'm currently working on. I've even made sure the permissions are given by checking the permissions in settings. Here's the logcat:


05-13 15:35:45.693 29696-29696 / com.example.hack.corrector E / SQLiteLog:( 14)无法在[5a3022e081]的第31282行打开文件
(14)os_unix.c:31282:(21)open(/data/user/0/com.example.hack.corrector/databases/)-
05-13 15:35:45.694 29696-29696 / com.example.hack.corrector E / SQLiteDatabase:无法打开数据库'/data/user/0/com.example.hack.corrector/databases/'。
android.database.sqlite.SQLiteCantOpenDatabaseException:未知错误(代码14):无法在android.database.sqlite.SQLiteConnection.nativeOpen(本机方法)
打开数据库
。 sqlite.SQLiteConnection.open(SQLiteConnection.java:207)
在android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:191)
在android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool。 java:463)android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
在android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:806)
在android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:791)
在android.database.sqlite.SQLiteDatabase .openDatabase(SQLiteDatabase.java:694)
在android.dat abase.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
在com.example.hakc.corrector.VocabDatabase.openDataBase(VocabDatabase.java:127)
在com.example.hakc.corrector中。在com.example.hakc.corrector.scrapeservice.onStartCommand(scrapeservice.java:23)中的scrapeservice.createDB(scrapeservice.java:31)
在android.app.ActivityThread.handleServiceArgs(ActivityThread.java: 3049)android.app.ActivityThread.access $ 2300(ActivityThread.java:154)中的
android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1479)
中的
。 os.Handler.dispatchMessage(Handler.java:102)
在android.os.Looper.loop(Looper.java:157)
在android.app.ActivityThread.main(ActivityThread.java:5571) java.lang.reflect.Method.invoke(本机方法)上的
com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:745)上的
。一个droid.internal.os.ZygoteInit.main(ZygoteInit.java:635)

05-13 15:35:45.693 29696-29696/com.example.hack.corrector E/SQLiteLog: (14) cannot open file at line 31282 of [5a3022e081] (14) os_unix.c:31282: (21) open(/data/user/0/com.example.hack.corrector/databases/) - 05-13 15:35:45.694 29696-29696/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.openDataBase(VocabDatabase.java:127) at com.example.hakc.corrector.scrapeservice.createDB(scrapeservice.java:31) at com.example.hakc.corrector.scrapeservice.onStartCommand(scrapeservice.java:23) 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)

这是数据库处理程序代码:

and here's the database handler code:

package com.example.hack.corrector;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class VocabDatabase extends SQLiteOpenHelper {

//The Android's default system path of your application database.
private static String DB_PATH = "";

private static String DB_NAME = "ztr.db";

private SQLiteDatabase myDataBase;

private final Context myContext;

/**
 * Constructor
 * Takes and keeps a reference of the passed context in order to access to the application assets and resources.
 *
 * @param context
 */
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;
}

/**
 * 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;
    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);
}

}

我已经检查了文件浏览器,并且数据库已经复制到位。但是仍然会发生错误。我从来没有遇到过实现相同数据库处理程序代码(Vocabdatabase)的其他应用程序的问题。我花了整整一天的时间来解决这个问题,但是没有任何效果……

I've checked the file explorer and the database has been copied and in place. But still, the error is occurring. I've never had problem with the other application that was implementing the same database handler code (Vocabdatabase). I've spent one and half a day trying to solve this problem but nothing is working...

推荐答案

您的问题是您正在尝试使用不包含数据库名称的路径打开。

Your issue is that you are trying to open using a path that does not include the database name.

ie无法打开14的原因是

i.e. the unable to open 14 is for

/data/user/0/com.example.hack.corrector/databases /

打开时应该尝试打开
/ data / user / 0 / com.example.hack.corrector / databases / ztr.db

whilst the open should be attempting to open /data/user/0/com.example.hack.corrector/databases/ztr.db

不使用完整路径将导致两个可能会导致混乱的问题。

Not using the full path will result in two issues which may well result in confusion.


  1. 当您检查数据库是否存在时,将发出消息(请注意,这样的数据库每次都将被复制,因为将永远无法找到(打开)数据库)。

  2. 当您尝试打开数据库时,消息也会发出,但后者将失败。

在两种情况下,正确的用法都应该是DB_PATH + DB_NAME,而不仅仅是DB_PATH。

In both situations the correct use should be DB_PATH + DB_NAME, not just DB_PATH.

以下是重写了您的数据库处理程序以合并以上内容,但同时也将数据库的检查更改为文件检查,因此打开错误14不是(从资产文件复制数据库时)不会显示错误。

The following is your Database Handler rewritten to incorporate the above but also to change the check for the database to be a check for the file so the open error 14 that is not an error isn't displayed (when the database is copied from the assets file).


  • 注释 // < ;<<< ???? 指示更改。

  • Comments //<<<< ???? indicate changes.

:-

public class VocabDatabase extends SQLiteOpenHelper {

    //The Android's default system path of your application database.
    //private static String DB_PATH = ""; //<<<< RMVD
    private static String DB_PATH_ALT; //<<<< ADDED
    private static String DB_NAME = "ztr.db";
    private SQLiteDatabase myDataBase;
    private final Context myContext;

    /**
     * Constructor
     * Takes and keeps a reference of the passed context in order to access to the application assets and resources.
     *
     * @param context
     */
    public VocabDatabase(Context context) {
        super(context, DB_NAME, null, 1);
        this.myContext = context;
        //this.DB_PATH = context.getApplicationInfo().dataDir + "/databases/"; //<<<< RMVD
        this.DB_PATH_ALT = context.getDatabasePath(DB_NAME).getPath(); //<<<< ADDED

    }

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

        //boolean dbExist = checkDataBase();  //<<<< RMVD 
        boolean dbExist = checkDataBaseAlt(); //<<<< CHANGED
        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");
            }
        }
    }
    //<<<< ADDED Alternative method checks the file rather than database
    //<<<<       as such no open error 14 messages
    /**
     * 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 checkDataBaseAlt() {
        //File chkdb = new File(myContext.getDatabasePath(DB_NAME).getPath()); //<<<< RMVD
        File chkdb = new File(DB_PATH_ALT); //<<<< ADDED
        return chkdb.exists();
    }

    /**
     * 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; //<<<< RMVD so no open error 14 uses alt method
            checkDB = SQLiteDatabase.openDatabase(
                    DB_PATH_ALT, //<<<< CHANGED
                    null, 
                    SQLiteDatabase.OPEN_READWRITE
            ); 

        } catch (SQLiteException e) {
            e.printStackTrace();
        }
        if (checkDB != null) {
            checkDB.close();
        }
        return checkDB != null; //<<<< simplified
    }

    /**
     * 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); //<<<< CHANGED

        // 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(DB_PATH_ALT); //<<<< CHANGED

        //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; //<<<< RMVD
        myDataBase = SQLiteDatabase.openDatabase(
                DB_PATH_ALT, //<<<< CHANGED
                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);
    }
}

这篇关于代码14:无法打开数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆