java - 尝试打开/assets 中的 sqlite 文件时收到 "Could not open database"错误

标签 java android sqlite android-listview android-sqlite

我正在尝试打开我创建并加载的 sqlite 数据库和我的项目的/assets。我使用一个类 MySQLiteHelper 来打开此数据库并处理升级等。

在我的 Activity 中,我创建了一个新的 MySQLiteHelper 实例...当我这样做时,它说它无法打开数据库(请参阅下面的 logcat)。

本来可以工作,但现在停止了。我很困惑为什么我现在会收到此错误...我回滚了更改,但仍然收到此错误。我认为这与我正在加载的文件有关?任何帮助将不胜感激。

打开sqlite的类:

package com.sembasys....;

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.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class MySQLiteHelper extends SQLiteOpenHelper {

    // The Android's default system path of your application database.
    private static String DB_PATH = "/data/data/com.sembasys.metrosleepnyc/databases/";
    private static String DB_NAME = "metrosleep";

    private SQLiteDatabase myDataBase;
    private final Context myContext;
    private static final int DATABASE_VERSION = 1;
    public static final String KEY_ID = "stop_id";
    public static final String LINE_ID = "line_id";
    public static final String STATION= "station_name";

    public MySQLiteHelper(Context context) {
        super(context, DB_NAME, null, DATABASE_VERSION);
        this.myContext = context;
    }

    /**
     * Creates a empty database on the system and rewrites it with your own
     * database.
     * */
    public void createDataBase() throws IOException {
        boolean dbExist = checkDataBase();
        if (dbExist) {
            Log.v("DB Exists", "db exists");

            // By calling this method here onUpgrade will be called on a
            // writeable database, but only if the version number has been
            // bumped
            this.getWritableDatabase();
        }
        dbExist = checkDataBase();
        if (!dbExist) {
            // 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 + DB_NAME;
            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(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;
        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_READONLY);

    }

    @Override
    public synchronized void close() {

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

        super.close();

    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (newVersion > oldVersion)
            Log.v("Database Upgrade", "Database version higher than old.");
        myContext.deleteDatabase(DB_NAME);
    }

}

我实现上述类的 Activity :

package com.sembasys....;


import com.actionbarsherlock.app.SherlockActivity;
import android.widget.SimpleCursorAdapter;
import android.annotation.TargetApi;
import android.app.ListActivity;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import android.support.v4.app.NavUtils;

public class ChooseRoute extends ListActivity  {


    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Show the Up button in the action bar.
        //getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        MySQLiteHelper myDbHelper = new MySQLiteHelper(null);
        myDbHelper = new MySQLiteHelper(this);


            try {
                myDbHelper.openDataBase();
            }catch(SQLException sqle){
                throw sqle;
            }


        if(isNetworkAvailable()) {

            setContentView(R.layout.activity_choose_route);

            TextView empty = (TextView) findViewById(android.R.id.empty);
            empty.setVisibility(View.VISIBLE);

            SQLiteDatabase db = myDbHelper.getReadableDatabase();

            String TABLE_NAME = "Stops";
            Cursor cursor = db.query(true, TABLE_NAME , new String[] { MySQLiteHelper.LINE_ID, MySQLiteHelper.STATION}, null, null, null, null, null, null);
             startManagingCursor(cursor);
            String[] columns = new String[] { MySQLiteHelper.STATION };

            // the XML defined views which the data will be bound to
            int[] to = new int[] { R.id.text };


            SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.todo_row, cursor, columns, to);
            setListAdapter(adapter);
            registerForContextMenu(getListView());


        } else {

            setContentView(R.layout.no_connection);

        }


    }

    private boolean isNetworkAvailable() {
        ConnectivityManager connectivityManager 
              = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null;
    }   


}

还有 logcat。

12-17 14:07:27.827: W/dalvikvm(23119): threadid=1: thread exiting with uncaught exception (group=0x40de8930)
12-17 14:07:27.847: E/AndroidRuntime(23119): FATAL EXCEPTION: main
12-17 14:07:27.847: E/AndroidRuntime(23119): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sembasys.metrosleepnyc/com.sembasys.metrosleepnyc.ChooseRoute}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.app.ActivityThread.access$600(ActivityThread.java:141)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.os.Handler.dispatchMessage(Handler.java:99)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.os.Looper.loop(Looper.java:137)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.app.ActivityThread.main(ActivityThread.java:5039)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at java.lang.reflect.Method.invokeNative(Native Method)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at java.lang.reflect.Method.invoke(Method.java:511)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at dalvik.system.NativeStart.main(Native Method)
12-17 14:07:27.847: E/AndroidRuntime(23119): Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at com.sembasys.metrosleepnyc.MySQLiteHelper.openDataBase(MySQLiteHelper.java:126)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at com.sembasys.metrosleepnyc.ChooseRoute.onCreate(ChooseRoute.java:36)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.app.Activity.performCreate(Activity.java:5104)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
12-17 14:07:27.847: E/AndroidRuntime(23119):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
12-17 14:07:27.847: E/AndroidRuntime(23119):    ... 11 more

最佳答案

根据你自己的代码,openDatabase()/databases文件夹中查找你的数据库,但是数据库仍然在/assets中code> 文件夹,直到您调用 createDatabase() (或直接调用 copyDatabase())。在尝试打开数据库之前,您必须调用createDataBase() 将数据库复制到适当的位置。

关于java - 尝试打开/assets 中的 sqlite 文件时收到 "Could not open database"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13920680/

相关文章:

android - 如何将对话框窗口背景设置为透明,而不影响其边距

java - 如何在 fragment Android中获取PackageManager

android - Assets 创建 - 9 补丁启动画面和屏幕密度

iphone - 数据库列中的最大值

java - 使用 AppNotificationReceiver 收到通知后将数据传递给 MainActivity

java - 为什么我的 Maven 插件不在构建生命周期中运行?

Java 逐元素求和 2 个数组

java - 如何在Java中创建可分配的、类似数字的类?

java - ListView 不显示存储在 SQLite 数据库中的项目

database - mac 存储 sqlite3 数据库的默认位置是什么