指定的目录或数据库文件不存在

时间:2018-08-28 09:01:01

标签: android database sqlite

多年以来,我一直在从事我的android项目,并且我一直在使用此代码进行数据库处理程序设置sqlite数据库,但是最近这些天,我在新笔记本电脑中安装了android studio,并开始运行我的项目,但是一旦出现此错误消息应用启动:

08-26 13:41:51.044 16032-16032/com.nileworx.flagsquiz E/SQLiteLog: (28) failed to open "/data/data/com.nileworx.flagsquiz/databases/FlagsQuiz" with flag (131072) and mode_t (0) due to error (2)
    (14) cannot open file at line 32561 of [a66a5b397b]
    (14) os_unix.c:32561: (2) open(/data/data/com.nileworx.flagsquiz/databases/FlagsQuiz) - 
08-26 13:41:51.054 16032-16032/com.nileworx.flagsquiz E/SQLiteDatabase: Failed to open database '/data/data/com.nileworx.flagsquiz/databases/FlagsQuiz'.
    android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 1294): Could not open database
    #################################################################
    Error Code : 1294 (SQLITE_CANTOPEN_ENOENT)
    Caused By : Specified directory or database file does not exist.
        (unknown error (code 1294): Could not open database)
    #################################################################
        at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:301)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:220)
        at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:512)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:206)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:178)
        at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:908)
        at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:878)
        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:699)
        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:674)
        at com.nileworx.flagsquiz.DataBaseHandler.checkDataBase(DataBaseHandler.java:86)
        at com.nileworx.flagsquiz.DataBaseHandler.createDataBase(DataBaseHandler.java:47)
        at com.nileworx.flagsquiz.DAO.<init>(DAO.java:52)
        at com.nileworx.flagsquiz.CustomDialog.<init>(CustomDialog.java:46)
        at com.nileworx.flagsquiz.MainActivity.onCreate(MainActivity.java:73)
        at android.app.Activity.performCreate(Activity.java:6609)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1134)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3113)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3275)
        at android.app.ActivityThread.access$1000(ActivityThread.java:218)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1744)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:145)
        at android.app.ActivityThread.main(ActivityThread.java:7007)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)

这是我的DatabaseHandler.java:

package com.nileworx.flagsquiz;

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

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

public class DataBaseHandler extends SQLiteOpenHelper {

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

    private static String DB_NAME = "FlagsQuiz";

    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 DataBaseHandler(Context context) {

        super(context, DB_NAME, null, 1);
        this.myContext = context;
        DB_PATH = context.getDatabasePath(DB_NAME).toString();
//      Log.e("path", DB_PATH);
    }

    // ==============================================================================

    /**
     * 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.getReadableDatabase();

            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() {

        SQLiteDatabase checkDB = null;

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

        } catch (SQLiteException e) {

            // database does't exist yet.

        }

        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("database/" + DB_NAME);

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

        // 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;
        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_READONLY);

    }

    // ==============================================================================

    @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) {

    }

    // 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.

}

这是我的数据库文件目录结构:
enter image description here

清单文件:

<?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.nileworx.flagsquiz"
    android:versionCode="7"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="18" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name"
        tools:replace="android:label"
        android:largeHeap="true"
        android:theme="@style/AppTheme" >
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
        <meta-data
            android:name="com.google.android.gms.games.APP_ID"
            android:value="@string/app_id" />

        <activity
            android:name="com.nileworx.flagsquiz.MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.nileworx.flagsquiz.UpdatesDialogActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Dialog" >
        </activity>
        <activity
            android:name="com.nileworx.flagsquiz.GameActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait" >
        </activity>
        <activity
            android:name="com.nileworx.flagsquiz.SettingsActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait" >
        </activity>
        <activity
            android:name="com.google.android.gms.ads.AdActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />

        <service android:name="com.nileworx.flagsquiz.GetUpdatesService" >
        </service>
        <service android:name="com.nileworx.flagsquiz.CheckUpdatesService" >
        </service>
    </application>

</manifest>

DAO.java

public DAO(Context context) {
        dbHandler = new DataBaseHandler(context);
        try {

            dbHandler.createDataBase();

        } catch (IOException ioe) {

            throw new Error("Unable to create database");

        }
        try {

            dbHandler.openDataBase();

        } catch (SQLException sqle) {

            throw sqle;

        }
        // Log.e("path2",
        // context.getDatabasePath("FootballFlagQuiz").toString());
    }

现在我该如何解决这个问题? 预先感谢!

2 个答案:

答案 0 :(得分:1)

根据您的代码,这是预期的。它在checkDatabase中打开时引发异常。俗话说db文件尚不存在。如果这是新安装,那将是正确的。您甚至正在编写代码以期望这样做-看到您的catch语句?这样就可以确定数据库是否是新数据库。

这里没有错。这将在任何设备上首次打印出来,并且仍然可以使用。如果要删除该消息,请从catch语句中删除日志记录。

答案 1 :(得分:0)

您的代码似乎不错。

我已经复制了您提供的所有代码,并试图重新创建您遇到的错误。

首先应该看到显示的堆栈跟踪,因为这是使用(在checkDB方法中)不可避免的被捕获(通过catch捕获)的结果:-

checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

,然后数据库不存在。堆栈跟踪不是来自致命异常。但是,堆栈跟踪本身是在openDatabase方法中发出的,因此不能轻易抑制。

因此,任何致命异常都必须在其他地方。您应该进一步检查日志。

运行代码时,如果没有正确命名的文件(例如 FlagsQuiz.txt 而不是 FlagsQuiz ),则会导致出现(请注意日志已添加到您的代码中)

即这两个用于测试的文件(扩展名NOTADB不是sqlite数据库,扩展名txt是添加了扩展名的有效sqlite数据库):-

enter image description here

结果:-

08-29 01:01:19.323 2602-2602/? D/CHKDB: Issuing openDatabase for path :- /data/data/so52053932.so52053932/databases/FlagsQuiz
08-29 01:01:19.331 2602-2602/? E/SQLiteLog: (14) cannot open file at line 30174 of [00bb9c9ce4]
    (14) os_unix.c:30174: (2) open(/data/data/so52053932.so52053932/databases/FlagsQuiz) - 
08-29 01:01:19.331 2602-2602/? E/SQLiteDatabase: Failed to open database '/data/data/so52053932.so52053932/databases/FlagsQuiz'.
    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 so52053932.so52053932.DataBaseHandler.checkDataBase(DataBaseHandler.java:89)
        at so52053932.so52053932.DataBaseHandler.createDataBase(DataBaseHandler.java:48)
        at so52053932.so52053932.DAO.<init>(DAO.java:17)
        at so52053932.so52053932.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)
08-29 01:01:19.331 2602-2602/? D/CHECKDB: SQLiteException has bee caught.
08-29 01:01:19.339 2602-2602/? D/ONCREATE: New Database has been created so ONCREATE has been invoked.
08-29 01:01:19.339 2602-2602/? D/CPYDB: Database Copy Initiated. Trying to open InputStream i.e. asset database/FlagsQuiz
08-29 01:01:19.339 2602-2602/? W/System.err: java.io.FileNotFoundException: database/FlagsQuiz
        at android.content.res.AssetManager.openAsset(Native Method)
        at android.content.res.AssetManager.open(AssetManager.java:315)
        at android.content.res.AssetManager.open(AssetManager.java:289)
        at so52053932.so52053932.DataBaseHandler.copyDataBase(DataBaseHandler.java:119)
        at so52053932.so52053932.DataBaseHandler.createDataBase(DataBaseHandler.java:62)
        at so52053932.so52053932.DAO.<init>(DAO.java:17)
        at so52053932.so52053932.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)
08-29 01:01:19.347 2602-2602/? W/System.err:     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)
08-29 01:01:19.347 2602-2602/? D/AndroidRuntime: Shutting down VM
08-29 01:01:19.347 2602-2602/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa62a0288)
08-29 01:01:19.347 2602-2602/? E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.Error: Error copying database
        at so52053932.so52053932.DataBaseHandler.createDataBase(DataBaseHandler.java:67)
        at so52053932.so52053932.DAO.<init>(DAO.java:17)
        at so52053932.so52053932.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)
  • 有3个异常(中间是第二个异常,当捕获到/捕获了最后一个异常时,第二个异常正在打印堆栈跟踪)。
  • 第一个异常不是致命异常,并且如上所述(即checkDB方法的预期异常)
  • 第二个异常是导致问题的实际异常。但是,它已被捕获(并且由于已打印其他代码,因此不会在您的代码中显示该内容,因为它未打印),这是由于在这种情况下找不到资产文件(例如,该代码为期望 FlagsQuiz 而不是 FlagsQuiz.txt FlagsQuixk.NOTADB )。
  • 第三个异常是由throw new Error("Error copying database"); createDatabase方法中发出的。 (没有帮助,因为在您的代码中隐藏了代码中的真正原因/位置)。

注意:在此阶段,实际上已经创建了基础数据库。**

按照08-29 01:01:19.339 2602-2602/? D/ONCREATE: New Database has been created so ONCREATE has been invoked.

例如设备资源管理器显示:-

如此,后续运行将不会尝试从Assets中复制数据库(如果存在)。 但是,除了 sqlite_master android_metadata 之外,现有的数据库将没有其他表。从应用程序的角度来看,这实际上是数据库为空(您希望至少有16k(如果我没记错的话)作为其他任何表的另一个4k页)。

enter image description here

因此,您的真实问题是另一个问题。我建议您可能要修改您的代码,使其包含临时调试信息(请参阅 // <<<<<< / strong>注释):-

DAO.java

public class DAO {

    DataBaseHandler dbHandler;

    public DAO(Context context) {
        dbHandler = new DataBaseHandler(context);
        try {

            dbHandler.createDataBase();

        } catch (IOException ioe) {

            throw new Error("Unable to create database");

        }
        try {

            dbHandler.openDataBase();
            Log.d("DAO","Attempting to open the database."); //<<<<< ADDED

        } catch (SQLException sqle) {
            Log.d("DAOCONSTRUCTOR","Error attempting to Open Database."); //<<<<< ADDED
            sqle.printStackTrace(); //<<<<< ADDED
            throw sqle;
        }
        // Log.e("path2",
        // context.getDatabasePath("FootballFlagQuiz").toString());
    }
}

DataBaseHandler.java

public class DataBaseHandler extends SQLiteOpenHelper {

    // The Androids default system path of your application database.
    private static String DB_PATH;

    private static String DB_NAME = "FlagsQuiz";

    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 DataBaseHandler(Context context) {

        super(context, DB_NAME, null, 1);
        this.myContext = context;
        DB_PATH = context.getDatabasePath(DB_NAME).toString();
//      Log.e("path", DB_PATH);
    }

    // ==============================================================================

    /**
     * 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.getReadableDatabase();

            try {

                copyDataBase();

            } catch (IOException e) {
                e.printStackTrace(); //<<<<< ADDED

                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() {

        SQLiteDatabase checkDB = null;

        try {
            String myPath = DB_PATH;
            Log.d("CHKDB","Issuing openDatabase for path :- " + myPath); //<<<<< ADDED
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
            boolean checkresult = checkDB != null; //<<<<< ADDED
            Log.d("CHKDB", "Result of check is " + String.valueOf(checkresult)); //<<<<< ADDED

        } catch (SQLiteException e) {
            Log.d("CHECKDB", "SQLiteException has bee caught."); //<<<<< ADDED

            // database does't exist yet.

        }

        if (checkDB != null) {
            Log.d("CHECKDB","DB exists so closing the opened DB."); //<<<<< ADDED
            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 {

        Log.d("CPYDB","Database Copy Initiated. Trying to open InputStream i.e. asset " + "database/" + DB_NAME); //<<<<< ADDED

        // Open your local db as the input stream
        InputStream myInput = myContext.getAssets().open("database/" + DB_NAME);
        Log.d("CPYDB","InputStream Opened successfully. Now trying to open OutputStream path = " + DB_PATH); //<<<<< ADDED

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

        // Open the empty db as the output stream
        OutputStream myOutput = new FileOutputStream(outFileName);
        Log.d("CPYDB","OutputStream Opened successfully. Now trying to copy from InputStream to OutputStream."); //<<<<< ADDED

        // transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
            Log.d("CPYDB","Copied " + String.valueOf(length) + " bytes."); //<<<<< ADDED
        }
        Log.d("CPYDB","Completed Copy from asset to DB. Flusing and closing Streams"); //<<<<< ADDED

        // Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();
        Log.d("CPYDB","Copy complete and all sterams flushed and closed. Copied " + String.valueOf(length) + "bytes."); //<<<<< ADDED
    }

    // ==============================================================================

    public void openDataBase() throws SQLException {

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

    }

    // ==============================================================================

    @Override
    public synchronized void close() {

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

        super.close();

    }

    // ==============================================================================

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.d("ONCREATE","New Database has been created so ONCREATE has been invoked."); //<<<<< ADDED

    }

    // ==============================================================================

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    // 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.

}

通过上述更改,也许可以更好地理解堆栈跟踪,您将能够查明遇到的实际错误。


有效运行

使用资产文件中的有效数据库运行代码,并将以下内容用作(调用)MainActivity:-

public class MainActivity extends AppCompatActivity {

    DAO myDAO;
    DataBaseHandler myDBhandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myDAO = new DAO(this);
        myDBhandler = myDAO.dbHandler;
        SQLiteDatabase db = myDBhandler.getWritableDatabase();
        Cursor csr = db.query("sqlite_master",null,null,null,null,null,null);
        while (csr.moveToNext()) {
            Log.d("COMPONENTS","Found " + csr.getString(csr.getColumnIndex("name")) + " Type is " + csr.getString(csr.getColumnIndex("type")));
        }
        csr.close();
    }
}

结果:-

08-29 01:14:06.139 2699-2699/? D/CHKDB: Issuing openDatabase for path :- /data/data/so52053932.so52053932/databases/FlagsQuiz
08-29 01:14:06.139 2699-2699/? E/SQLiteLog: (14) cannot open file at line 30174 of [00bb9c9ce4]
    (14) os_unix.c:30174: (2) open(/data/data/so52053932.so52053932/databases/FlagsQuiz) - 
08-29 01:14:06.139 2699-2699/? E/SQLiteDatabase: Failed to open database '/data/data/so52053932.so52053932/databases/FlagsQuiz'.
    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 so52053932.so52053932.DataBaseHandler.checkDataBase(DataBaseHandler.java:89)
        at so52053932.so52053932.DataBaseHandler.createDataBase(DataBaseHandler.java:48)
        at so52053932.so52053932.DAO.<init>(DAO.java:17)
        at so52053932.so52053932.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)
08-29 01:14:06.139 2699-2699/? D/CHECKDB: SQLiteException has bee caught.
08-29 01:14:06.151 2699-2699/? D/ONCREATE: New Database has been created so ONCREATE has been invoked.
08-29 01:14:06.151 2699-2699/? D/CPYDB: Database Copy Initiated. Trying to open InputStream i.e. asset database/FlagsQuiz
    InputStream Opened successfully. Now trying to open OutputStream path = /data/data/so52053932.so52053932/databases/FlagsQuiz
    OutputStream Opened successfully. Now trying to copy from InputStream to OutputStream.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Copied 1024 bytes.
    Completed Copy from asset to DB. Flusing and closing Streams
    Copy complete and all sterams flushed and closed. Copied -1bytes.
08-29 01:14:06.151 2699-2699/? D/DAO: Attempting to open the database.
08-29 01:14:06.159 2699-2699/? D/COMPONENTS: Found android_metadata Type is table
    Found PrivateList Type is table
    Found PrivateProduct Type is table
    Found List_Product Type is table
    Found sqlite_autoindex_List_Product_1 Type is index

备用数据库检查

以下代码是一种替代方法,该方法在不发出SQLiteException的情况下检查数据库是否存在(假定为有效的数据库)。即它会检查数据库文件而不是数据库(如果复制失败,它也不会创建空数据库):-

private boolean ifDatabaseExists(String dbpath) {
    File db = new File(dbpath);
    if(db.exists()) return true;
    File dir = new File(db.getParent());
    if (!dir.exists()) {
        dir.mkdirs();
    }
    return false;
}
  • 这可以用作checkDB方法的替代方法。