获得"无法打开数据库"错误抄袭资产SQLite数据库时,在安卓4.2 [英] Getting "Failed to open database" error when copying a sqlite database from assets In Android 4.2

查看:185
本文介绍了获得"无法打开数据库"错误抄袭资产SQLite数据库时,在安卓4.2的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的code正常工作为Android 2.3,但我不知道为什么它不针对Android 4.2的工作

我的异常日志是这里

  9月一日至17日:54:04.411:E / SQLiteLog(24202):(14)无法打开文件在30176行[00bb9c9ce4]
9月1号至17日:54:04.411:E / SQLiteLog(24202):(14)os_unix.c:30176:(2)开(/data/data/com.example.myapp/databases/myapp.db) - 
无法打开数据库/data/data/com.example.mypapp/databases/myapp.db。
android.database.sqlite.SQLiteCantOpenDatabaseException:未知错误(code 14):无法打开数据库
在android.database.sqlite.SQLiteConnection.nativeOpen(本机方法)
在android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
在android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
在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:804​​)
在android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
在android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
在android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
在com.example.myapp.DataBaseHelper.checkDataBase(DataBaseHelper.java:80)
在com.example.myapp.DataBaseHelper.createDataBase(DataBaseHelper.java:47)
在com.example.myapp.MainActivity.onCreate(MainActivity.java:61)
在android.app.Activity.performCreate(Activity.java:5104)
在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
在android.app.ActivityThread.access $ 600(ActivityThread.java:141)
在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1234)
在android.os.Handler.dispatchMessage(Handler.java:99)
在android.os.Looper.loop(Looper.java:137)
在android.app.ActivityThread.main(ActivityThread.java:5039)
在java.lang.reflect.Method.invokeNative(本机方法)
在java.lang.reflect.Method.invoke(Method.java:511)
在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:793)
在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
在dalvik.system.NativeStart.main(本机方法)
 

我的 MainActivity.java

 公共类MainActivity延伸活动{

    公共无效的onCreate(包冰柱){

        super.onCreate(冰柱);

        的setContentView(R.layout.activity_main);

        DataBaseHelper myDbHelper;
        myDbHelper =新DataBaseHelper(本);

        尝试 {

            myDbHelper.createDataBase();

        }赶上(IOException异常IOE){

            抛出新的错误(无法创建数据库);
        }

        尝试 {
            myDbHelper.openDataBase();

        }赶上(的SQLException SQLE){

            扔SQLE;

        } 最后 {

            myDbHelper.close();
        }
}}
 

我的 DatabaseHelper.java

 公共类DataBaseHelper扩展SQLiteOpenHelper {

    //而Android的默认系统应用程序的数据库路径。
    私有静态字符串DB_PATH =/data/data/com.example.myapp/databases/;

    私有静态字符串DB_NAME =myapp.db;

    私人SQLiteDatabase MyDatabase的;

    私人最终语境myContext;

    / **
     *构造函数
     *注意到并保持传递的上下文中的一个参考,以便访问该应用程序的资产和资源。
     * @参数方面
     * /
    公共DataBaseHelper(上下文的背景下){

        超级(上下文,DB_NAME,空,1);
        this.myContext =背景;
    }

  / **
     *在系统上创建一个空数据库,并与自己的数据库重写它。
     * * /
    公共无效的CreateDatabase()抛出IOException异常{

        布尔dbExist = checkDataBase();

        如果(dbExist){
            //什么也不做 - 数据库中已存在
        }其他{

            //通过调用这个方法和空的数据库将被创建到系统​​默认路径
               //你的应用程序,所以我们要能够覆盖数据库,我们的数据库。
            this.getReadableDatabase();

            尝试 {

                copyDataBase();

            }赶上(IOException异常E){

                抛出新的错误(错误复制数据库);

            }
        }

    }

    / **
     *检查数据库中已存在,以避免重新复制每次打开应用程序时,该文件。
     * @返回true,如果它存在,虚假的,如果它不
     * /
    私人布尔checkDataBase(){

        SQLiteDatabase CHECKDB = NULL;

        尝试{
            字符串mypath中= DB_PATH + DB_NAME;
            CHECKDB = SQLiteDatabase.openDatabase(mypath中,空,SQLiteDatabase.OPEN_READONLY);

        }赶上(SQLiteException E){
            Log.i(Hellloooo,e.getMessage());
            //数据库的简化版,存在。

        }

        如果(CHECKDB!= NULL){

            checkDB.close();

        }

        返回CHECKDB!= NULL?真假;
    }

    / **
     *复制你的数据库从当地的资产文件夹在刚才创建的空数据库
     *系统文件夹,从那里它可以被访问和处理。
     *这是通过transfering字节流进行。
     * * /
    私人无效copyDataBase()抛出IOException异常{

        //打开本地数据库作为输入流
        InputStream的myInput = myContext.getAssets()开(DB_NAME)。

        //路径刚刚创建的空分贝
        字符串outFileName = DB_PATH + DB_NAME;

        //打开空分贝的输出流
        的OutputStream myOutput =新的FileOutputStream(outFileName);

        //传输的字节从inputfile中的OUTPUTFILE
        byte []的缓冲区=新的字节[1024];
        INT长;
        而((长度= myInput.read(缓冲液))大于0){
            myOutput.write(缓冲液,0,长度);
        }

        //关闭流
        myOutput.flush();
        myOutput.close();
        myInput.close();

    }

    公共无效的openDatabase()抛出的SQLException {

        //打开数据库
        字符串mypath中= DB_PATH + DB_NAME;
        MyDatabase的= SQLiteDatabase.openDatabase(mypath中,空,SQLiteDatabase.OPEN_READONLY);

    }

    @覆盖
    市民同步无效的close(){

            如果(MyDatabase的!= NULL)
                myDataBase.close();

            super.close();

    }

    @覆盖
    公共无效的onCreate(SQLiteDatabase DB){

    }

    @覆盖
    公共无效onUpgrade(SQLiteDatabase分贝,INT oldVersion,诠释静态网页){

    }

        //添加您的公共辅助方法来访问,并从数据库中获取的内容。
       //你可以做返回游标返回myDataBase.query(....),因此这将会是很容易
       //你来创造适配器的意见。

}
 

解决方案

我不得不修改 checkDataBase()

 私人布尔checkDataBase(){
        布尔CHECKDB = FALSE;
        尝试{
            字符串mypath中= myContext.getFilesDir()getAbsolutePath()代替(文件,数据库)+文件分割符+ DB_NAME。;
            文件DBFILE =新的文件(mypath中);
            CHECKDB = dbfile.exists();
        }
        赶上(SQLiteException E){
            的System.out.println(数据库不存在);
        }

        返回CHECKDB;
    }
 

My Code works fine For Android 2.3 but i don't know why it doesn't work for Android 4.2

My Exception log is here

01-17 09:54:04.411: E/SQLiteLog(24202): (14) cannot open file at line 30176 of [00bb9c9ce4]
01-17 09:54:04.411: E/SQLiteLog(24202): (14) os_unix.c:30176: (2) open(/data/data/com.example.myapp/databases/myapp.db) - 
Failed to open database '/data/data/com.example.mypapp/databases/myapp.db'.
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 com.example.myapp.DataBaseHelper.checkDataBase(DataBaseHelper.java:80)
at com.example.myapp.DataBaseHelper.createDataBase(DataBaseHelper.java:47)
at com.example.myapp.MainActivity.onCreate(MainActivity.java:61)
at android.app.Activity.performCreate(Activity.java:5104)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5039)
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:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)

My MainActivity.java

public class MainActivity extends Activity {

    public void onCreate(Bundle icicle) {

        super.onCreate(icicle);

        setContentView(R.layout.activity_main);

        DataBaseHelper myDbHelper;
        myDbHelper = new DataBaseHelper(this);

        try {

            myDbHelper.createDataBase();

        } catch (IOException ioe) {         

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

        try {
            myDbHelper.openDataBase();

        } catch (SQLException sqle) {

            throw sqle;

        } finally {

            myDbHelper.close();
        }
}}

My DatabaseHelper.java

public class DataBaseHelper extends SQLiteOpenHelper{

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

    private static String DB_NAME = "myapp.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 DataBaseHelper(Context context) {

        super(context, DB_NAME, null, 1);
        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){
            //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 + DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

        }catch(SQLiteException e){  
            Log.i("Hellloooo", e.getMessage());
            //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) {

    }

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

}

解决方案

I had to modify checkDataBase() to

 private boolean checkDataBase(){
        boolean checkdb = false;
        try{
            String myPath = myContext.getFilesDir().getAbsolutePath().replace("files", "databases")+File.separator + DB_NAME;
            File dbfile = new File(myPath);                
            checkdb = dbfile.exists();
        }
        catch(SQLiteException e){
            System.out.println("Database doesn't exist");
        }

        return checkdb;
    }

这篇关于获得"无法打开数据库"错误抄袭资产SQLite数据库时,在安卓4.2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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