【问题标题】:Having trouble copying an existing sqlite db file from assets to android project将现有的 sqlite db 文件从资产复制到 android 项目时遇到问题
【发布时间】:2019-02-21 08:15:19
【问题描述】:

我有以下代码:

private void copyDataBase() throws IOException {
    Context context = this.getApplicationContext();

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

    // Define output file name
    File outfile = new File(context.getDatabasePath(DB_NAME).toString());
    outfile.setWritable(true);

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

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

但是,它在 OutputStream 变量上一直失败。不断抛出的错误是:

java.io.FileNotFoundException ... mydb.db: open failed: ENOTDIR (Not a directory)

我的 SQLite 文件在项目的 assets 目录中,我的 minSdkVersion19targetSdkVersion28

这是来自下面 cmets 的函数调用的更新版本,它仍然失败。

private void copyDataBase() throws IOException {
    Context context = this.getApplicationContext();

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

    // Define output file name
    File outfile = new File(context.getDatabasePath(DB_NAME).toString());

    try {
        // Define path to database file and make directories if necessary
        File dir = new File(DB_PATH);
        if (!dir.exists()) {
            boolean madeDirectory = dir.mkdirs();
            Log.d(TAG, String.format("copyDataBase: Made directories: %s", madeDirectory));
        }

        if (!outfile.exists()){
            outfile.createNewFile();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

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

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

变量DB_NAME只是我正在使用的数据库文件的名称myExample.db

getDatabasePath 函数调用生成的字符串是"/data/data/projectname/databases/myExample.db

【问题讨论】:

    标签: java android sqlite copy assets


    【解决方案1】:

    我相信您的问题是数据库文件夹不存在。而只是 /data/data/<the_package>/ 存在。

    所以尝试根据 cmets 添加代码:-

    File outfile = new File(context.getDatabasePath(DB_NAME).toString()); //<<<<<<<<< EXISTING LINE
    if (!outfile.getParentFile().exists()) { //<<<<<<<<<< ADDED
        outfile.getParentFile().mkdirs(); //<<<<<<<<<< ADDED
    } //<<<<<<<<<< ADDED
    

    我倾向于在检查数据库是否存在时创建目录,例如:-

    private boolean checkDataBase() {
        /**
         * Does not open the database instead checks to see if the file exists
         * also creates the databases directory if it does not exist
         * (the real reason why the database is opened, which appears to result in issues)
         */
    
        File db = new File(myContext.getDatabasePath(DB_NAME).getPath()); //Get the file name of the database
        if (db.exists()) return true; // If it exists then return doing nothing
    
        // Get the parent (directory in which the database file would be)
        File dbdir = db.getParentFile();
        // If the directory does not exist then make the directory (and higher level directories if need be)
        if (!dbdir.exists()) {
            dbdir.mkdirs();
        }
        return false;
    }
    

    复制问题

    使用代码:-

    private void copyDataBase() throws IOException {
    
            final String TAG = "COPYDATABASE";
    
            //Open your local db as the input stream
            Log.d(TAG,"Initiated Copy of the database file " + DB_NAME + " from the assets folder.");
            InputStream myInput = myContext.getAssets().open(DB_NAME); // Open the Asset file
            String dbpath = myContext.getDatabasePath(DB_NAME).getPath();
            Log.d(TAG,"Asset file " + DB_NAME + " found so attmepting to copy to " + dbpath);
    
            // Path to the just created empty db
            //String outFileName = DB_PATH + DB_NAME;
            //Open the empty db as the output stream
            File outfile = new File(myContext.getDatabasePath(DB_NAME).toString());
            Log.d("DBPATH","path is " + outfile.getPath());
            outfile.setWritable(true);
            //OutputStream myoutputx2 = new FileOutputStream(outfile);
            if (!outfile.getParentFile().exists()) {
                outfile.getParentFile().mkdirs();
            }
    
            OutputStream myOutput = new FileOutputStream(outfile);
            //transfer bytes from the inputfile to the outputfile
            byte[] buffer = new byte[buffer_size];
            int length;
            while ((length = myInput.read(buffer))>0) {
                blocks_copied++;
                Log.d(TAG,"Ateempting copy of block " + String.valueOf(blocks_copied) + " which has " + String.valueOf(length) + " bytes.");
                myOutput.write(buffer, 0, length);
                bytes_copied += length;
            }
            Log.d(TAG,
                    "Finished copying Database " + DB_NAME +
                            " from the assets folder, to  " + dbpath +
                            String.valueOf(bytes_copied) + "were copied, in " +
                            String.valueOf(blocks_copied) + " blocks of size " +
                            String.valueOf(buffer_size) + "."
            );
            //Close the streams
            myOutput.flush();
            myOutput.close();
            myInput.close();
            Log.d(TAG,"All Streams have been flushed and closed.");
        }
    

    导致您收到的错误:-

    02-21 10:17:25.975 7604-7604/so.cdfa D/VERSION: Build Version is 22
    02-21 10:17:25.975 7604-7604/so.cdfa D/DBPATH: DB Path is /data/data/so.cdfa/databases/db
    02-21 10:17:25.975 7604-7604/so.cdfa D/DBPATH: DB Path is /data/data/so.cdfa/databases/db
    02-21 10:17:25.976 7604-7604/so.cdfa D/COPYDATABASE: Initiated Copy of the database file db from the assets folder.
    02-21 10:17:25.976 7604-7604/so.cdfa D/COPYDATABASE: Asset file db found so attmepting to copy to /data/data/so.cdfa/databases/db
    02-21 10:17:25.976 7604-7604/so.cdfa D/DBPATH: path is /data/data/so.cdfa/databases/db
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err: java.io.FileNotFoundException: /data/data/so.cdfa/databases/db: open failed: ENOENT (No such file or directory)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:456)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at so.cdfa.DBHelper.copyDataBase(DBHelper.java:120)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at so.cdfa.DBHelper.createDataBase(DBHelper.java:58)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at so.cdfa.DBHelper.<init>(DBHelper.java:32)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at so.cdfa.MainActivity.onCreate(MainActivity.java:60)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at android.app.Activity.performCreate(Activity.java:5990)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
    02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at android.app.ActivityThread.access$800(ActivityThread.java:151)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at android.os.Looper.loop(Looper.java:135)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5254)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at java.lang.reflect.Method.invoke(Method.java:372)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at libcore.io.Posix.open(Native Method)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:442)
    02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:  ... 19 more
    02-21 10:17:25.977 7604-7604/so.cdfa D/AndroidRuntime: Shutting down VM
    02-21 10:17:25.977 7604-7604/so.cdfa E/AndroidRuntime: FATAL EXCEPTION: main
        Process: so.cdfa, PID: 7604
        java.lang.RuntimeException: Unable to start activity ComponentInfo{so.cdfa/so.cdfa.MainActivity}: java.lang.RuntimeException: Error copying database (see stack-trace above)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            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:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
         Caused by: java.lang.RuntimeException: Error copying database (see stack-trace above)
            at so.cdfa.DBHelper.createDataBase(DBHelper.java:65)
    

    将代码修改为(根据原始答案):-

    private void copyDataBase() throws IOException {
    
        final String TAG = "COPYDATABASE";
    
        //Open your local db as the input stream
        Log.d(TAG,"Initiated Copy of the database file " + DB_NAME + " from the assets folder.");
        InputStream myInput = myContext.getAssets().open(DB_NAME); // Open the Asset file
        String dbpath = myContext.getDatabasePath(DB_NAME).getPath();
        Log.d(TAG,"Asset file " + DB_NAME + " found so attmepting to copy to " + dbpath);
    
        // Path to the just created empty db
        //String outFileName = DB_PATH + DB_NAME;
        //Open the empty db as the output stream
        File outfile = new File(myContext.getDatabasePath(DB_NAME).toString());
        Log.d("DBPATH","path is " + outfile.getPath());
        outfile.setWritable(true); //<<<<<<<<<< not required as writable access exists
        //OutputStream myoutputx2 = new FileOutputStream(outfile);
        if (!outfile.getParentFile().exists()) {
            outfile.getParentFile().mkdirs();
        }
    
        OutputStream myOutput = new FileOutputStream(outfile);
        //transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[buffer_size];
        int length;
        while ((length = myInput.read(buffer))>0) {
            blocks_copied++;
            Log.d(TAG,"Ateempting copy of block " + String.valueOf(blocks_copied) + " which has " + String.valueOf(length) + " bytes.");
            myOutput.write(buffer, 0, length);
            bytes_copied += length;
        }
        Log.d(TAG,
                "Finished copying Database " + DB_NAME +
                        " from the assets folder, to  " + dbpath +
                        String.valueOf(bytes_copied) + "were copied, in " +
                        String.valueOf(blocks_copied) + " blocks of size " +
                        String.valueOf(buffer_size) + "."
        );
        //Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();
        Log.d(TAG,"All Streams have been flushed and closed.");
    }
    

    结果:-

    02-21 10:24:31.808 7972-7972/? D/VERSION: Build Version is 22
    02-21 10:24:31.808 7972-7972/? D/DBPATH: DB Path is /data/data/so.cdfa/databases/db
    02-21 10:24:31.808 7972-7972/? D/DBPATH: DB Path is /data/data/so.cdfa/databases/db
    02-21 10:24:31.808 7972-7972/? D/COPYDATABASE: Initiated Copy of the database file db from the assets folder.
    02-21 10:24:31.808 7972-7972/? D/COPYDATABASE: Asset file db found so attmepting to copy to /data/data/so.cdfa/databases/db
    02-21 10:24:31.808 7972-7972/? D/DBPATH: path is /data/data/so.cdfa/databases/db
    02-21 10:24:31.809 7972-7972/? D/COPYDATABASE: Ateempting copy of block 1 which has 1024 bytes.
    02-21 10:24:31.809 7972-7972/? D/COPYDATABASE: Ateempting copy of block 2 which has 1024 bytes.
    02-21 10:24:31.809 7972-7972/? D/COPYDATABASE: Ateempting copy of block 3 which has 1024 bytes.
    02-21 10:24:31.809 7972-7972/? D/COPYDATABASE: Ateempting copy of block 4 which has 1024 bytes.
    02-21 10:24:31.809 7972-7972/? D/COPYDATABASE: Ateempting copy of block 5 which has 1024 bytes.
    02-21 10:24:31.809 7972-7972/? D/COPYDATABASE: Ateempting copy of block 6 which has 1024 bytes.
    02-21 10:24:31.809 7972-7972/? D/COPYDATABASE: Ateempting copy of block 7 which has 1024 bytes.
    02-21 10:24:31.809 7972-7972/? D/COPYDATABASE: Ateempting copy of block 8 which has 1024 bytes.
    02-21 10:24:31.809 7972-7972/? D/COPYDATABASE: Ateempting copy of block 9 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 10 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 11 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 12 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 13 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 14 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 15 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 16 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 17 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 18 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 19 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 20 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 21 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 22 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 23 which has 1024 bytes.
    02-21 10:24:31.810 7972-7972/? D/COPYDATABASE: Ateempting copy of block 24 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 25 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 26 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 27 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 28 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 29 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 30 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 31 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 32 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 33 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 34 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 35 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 36 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 37 which has 1024 bytes.
    02-21 10:24:31.811 7972-7972/? D/COPYDATABASE: Ateempting copy of block 38 which has 1024 bytes.
    02-21 10:24:31.812 7972-7972/? D/COPYDATABASE: Ateempting copy of block 39 which has 1024 bytes.
    02-21 10:24:31.812 7972-7972/? D/COPYDATABASE: Ateempting copy of block 40 which has 1024 bytes.
    02-21 10:24:31.812 7972-7972/? D/COPYDATABASE: Finished copying Database db from the assets folder, to  /data/data/so.cdfa/databases/db40960were copied, in 40 blocks of size 1024.
    02-21 10:24:31.812 7972-7972/? D/COPYDATABASE: All Streams have been flushed and closed.
    

    上面的代码是从整个 DBHelper 中提取的

    • 日志将被删除,许多 cmets 发表评论并修复了一个问题,即可以清理代码。

    :-

    public class DBHelper extends SQLiteOpenHelper {
    
        private static String DB_NAME = "db";
        private SQLiteDatabase myDataBase;
        private final Context myContext;
    
        private int bytes_copied = 0;
        private static int buffer_size = 1024;
        private int blocks_copied = 0;
    
        public DBHelper(Context context) {
            super(context, DB_NAME, null, 1);
    
            this.myContext = context;
            // Check for and create (copy DB from assets) when constructing the DBHelper
            if (!checkDataBase()) {
                bytes_copied = 0;
                blocks_copied = 0;
                createDataBase();
            }
        }
    
        /**
         * Creates an empty database on the system and rewrites it with your own database.
         * */
        public void createDataBase() {
    
            boolean dbExist = checkDataBase(); // Double check
            if(dbExist){
                //do nothing - database already exist
            } else {
                //By calling this method an 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();
                //<<<<<<<<<< Dimsiss the above comment
                //By calling this method an empty database IS NOT created nor are the related -shm and -wal files
                //The method that creates the database is flawed and was only used to resolve the issue
                //of the copy failing in the absence of the databases directory.
                //The dbExist method, now utilised, checks for and creates the database directory, so there
                //is then no need to create the database just to create the databases library. As a result
                //the -shm and -wal files will not exist and thus result in the error associated with
                //Android 9+ failing with due to tables not existining after an apparently successful
                //copy.
                try {
                    copyDataBase();
                } catch (IOException e) {
                    File db = new File(myContext.getDatabasePath(DB_NAME).getPath());
                    if (db.exists()) {
                        db.delete();
                    }
                    e.printStackTrace();
                    throw new RuntimeException("Error copying database (see stack-trace above)");
                }
            }
        }
    
        /**
         * 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() {
            /**
             * Does not open the database instead checks to see if the file exists
             * also creates the databases directory if it does not exists
             * (the real reason why the database is opened, which appears to result in issues)
             */
    
            File db = new File(myContext.getDatabasePath(DB_NAME).getPath()); //Get the file name of the database
            Log.d("DBPATH","DB Path is " + db.getPath());
            if (db.exists()) return true; // If it exists then return doing nothing
    
            // Get the parent (directory in which the database file would be)
            File dbdir = db.getParentFile();
            // If the directory does not exits then make the directory (and higher level directories)
            /*
            if (!dbdir.exists()) {
                db.getParentFile().mkdirs();
                dbdir.mkdirs();
            }
            */
            return 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 {
    
            final String TAG = "COPYDATABASE";
    
            //Open your local db as the input stream
            Log.d(TAG,"Initiated Copy of the database file " + DB_NAME + " from the assets folder.");
            InputStream myInput = myContext.getAssets().open(DB_NAME); // Open the Asset file
            String dbpath = myContext.getDatabasePath(DB_NAME).getPath();
            Log.d(TAG,"Asset file " + DB_NAME + " found so attmepting to copy to " + dbpath);
    
            // Path to the just created empty db
            //String outFileName = DB_PATH + DB_NAME;
            //Open the empty db as the output stream
            File outfile = new File(myContext.getDatabasePath(DB_NAME).toString());
            Log.d("DBPATH","path is " + outfile.getPath());
            //outfile.setWritable(true); // NOT NEEDED as permission already applies
            //OutputStream myoutputx2 = new FileOutputStream(outfile);
            /* Note done in checkDatabase method
            if (!outfile.getParentFile().exists()) {
                outfile.getParentFile().mkdirs();
            }
            */
    
            OutputStream myOutput = new FileOutputStream(outfile);
            //transfer bytes from the inputfile to the outputfile
            byte[] buffer = new byte[buffer_size];
            int length;
            while ((length = myInput.read(buffer))>0) {
                blocks_copied++;
                Log.d(TAG,"Ateempting copy of block " + String.valueOf(blocks_copied) + " which has " + String.valueOf(length) + " bytes.");
                myOutput.write(buffer, 0, length);
                bytes_copied += length;
            }
            Log.d(TAG,
                    "Finished copying Database " + DB_NAME +
                            " from the assets folder, to  " + dbpath +
                            String.valueOf(bytes_copied) + "were copied, in " +
                            String.valueOf(blocks_copied) + " blocks of size " +
                            String.valueOf(buffer_size) + "."
            );
            //Close the streams
            myOutput.flush();
            myOutput.close();
            myInput.close();
            Log.d(TAG,"All Streams have been flushed and closed.");
        }
    
    
        @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) {
        }
    
        @Override
        public void onConfigure(SQLiteDatabase db) {
            super.onConfigure(db);
            Log.d("DBCONFIGURE","Database has been configured ");
        }
    
        @Override
        public void onOpen(SQLiteDatabase db) {
            super.onOpen(db);
            Log.d("DBOPENED","Database has been opened.");
        }
    }  
    

    【讨论】:

    • 不。还是不行。我仍然得到 FileNotFoundException /data/data/...myDb.db: open failed: ENOTDIR (Not a directory)
    • @Jasonca1 在Log.d("DBPATH","DB Path is " + outfile.getPath()); 行之后立即添加Log.d("DBPATH","DB Path is " + outfile.getPath()); 行之后,您能否编辑您的问题以包含堆栈跟踪。
    • 日志输出为:/data/data/com.myproject.myprojectpackage/databases/mydatabase.db
    • @Jasonca1 我相信你没有正确介绍目录创建代码,也许你离开了?。答案已被修改以显示复制您的问题并且修复工作的代码。 (不是它不是最干净的代码,因为它是对我使用过的现有代码的改编(对于我给出的另一个答案))
    • 我将尝试您修改后的解决方案并发布我的结果。
    【解决方案2】:

    错误提示找不到输出文件。因此,您需要先创建一个才能打开它并从资产中复制。

    try {       
        String DB_PATH = "/data/data/" + "your.application.package.name" + "/databases/";
        File dir = new File(DB_PATH);
        if (!dir.exists()) dir.mkdir();
        File f = new File(DB_PATH + DB_NAME);
        if (!f.exists()) {
            f.createNewFile();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    // Then it should work
    OutputStream mOutput = new FileOutputStream(f);
    

    【讨论】:

    • createNewFile 函数调用失败
    • 不应该。它可能会显示错误,此代码段可能会引发错误,使用 try/catch 块可以轻松避免该错误。我正在使用try/catch 块更新答案。请看一看。
    • @Raez Murshed 它仍然失败。仍然收到错误代码:java.io.IOException: open failed: ENOTDIR (Not a directory)
    • 你能用你输出目录的代码段更新问题吗?好让我看看?您的应用程序包名称是什么?
    猜你喜欢
    • 1970-01-01
    • 2015-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-15
    • 1970-01-01
    • 1970-01-01
    • 2021-07-27
    相关资源
    最近更新 更多