将Android应用程序SQLite数据库复制到Google云端硬盘时,“数据库磁盘映像格式错误”

时间:2014-06-02 03:51:03

标签: android database sqlite

我正在尝试在我的应用中按需备份和恢复数据库。该代码确实创建了一个具有正确名称的Google云端硬盘文件,但是当我恢复它或在驱动器中查看时,我得到了#34;数据库磁盘映像格式错误"。

从我的研究中得到最好的"我可以找到的解释是在上传之前数据库没有关闭。

我在SQLiteHelper上调用close()

我缺少什么?
我犯了错误吗? 有不同的原因吗?我发现提前写入记录也可能导致这种情况。我禁用了WAL仍然有问题。如何在上传之前检查是否格式错误?

MySQLiteHelper db;
private DriveFile mfile;

private File getDbPath() {
    return this.getDatabasePath(DATABASE_NAME);
}

private ResultCallback<ContentsResult> writeToFile = new ResultCallback<ContentsResult>() {

    @Override
    public void onResult(ContentsResult result) {

        if (!result.getStatus().isSuccess()) {
            Log.v(TAG, "Error opening file");
            return;
        }
        db.close();
        try {
            FileInputStream is = new FileInputStream(getDbPath());
            BufferedInputStream in = new BufferedInputStream(is);
            byte[] buffer = new byte[8 * 1024];
            Contents content = result.getContents();
            BufferedOutputStream out = new BufferedOutputStream(content.getOutputStream());
            int n = 0;
            while( ( n = in.read(buffer) ) > 0 ) {
                out.write(buffer, 0, n);
            }

            in.close();
            mfile.commitAndCloseContents(mGoogleApiClient, content).setResultCallback(new ResultCallback<Status>() {
                @Override
                public void onResult(Status result) {
                    showMessage("file done");
                    db = new MySQLiteHelper(context);
                }
            });
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
};

private void openNewFile (ContentsResult result) {
    String mimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType("db"); 
    MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
            .setTitle(DATABASE_NAME) 
            .setMimeType(mimeType)
            .setPinned(true)
            .setStarred(true).build();

    Drive.DriveApi.getRootFolder(mGoogleApiClient)  //getAppFolder
            .createFile(mGoogleApiClient, changeSet, result.getContents())
            .setResultCallback(new ResultCallback<DriveFileResult>() {

                @Override
                public void onResult(DriveFileResult result) {
                    if (!result.getStatus().isSuccess()) {
                        Log.v(TAG, "Error while trying to create the file");
                        return;
                    }
                    mfile = result.getDriveFile();
                    mfile.openContents(mGoogleApiClient, DriveFile.MODE_WRITE_ONLY, null).setResultCallback(writeToFile);
                }
            });
}

public void backupDB(View v) {
    db.close();
    Drive.DriveApi.newContents(mGoogleApiClient).setResultCallback(new ResultCallback<ContentsResult>() {
        @Override
        public void onResult(ContentsResult result) {
            if (!result.getStatus().isSuccess()) {
                Log.v(TAG, "Error while trying to create new file contents");
                return;
            }
            final ContentsResult res = result;
            Query query = new Query.Builder().addFilter(Filters.eq(SearchableField.TITLE, DATABASE_NAME)).build();
            //TODO change this to appfolder search eventually
            Drive.DriveApi.query(mGoogleApiClient, query)
                    .setResultCallback(new ResultCallback<MetadataBufferResult>() {
                        @Override
                        public void onResult(MetadataBufferResult result) {
                            MetadataBuffer mdb = result.getMetadataBuffer();
                            if (mdb == null) {
                                openNewFile(res);
                            } else {
                                for (Metadata md : mdb) {
                                    if (!md.isTrashed()) {
                                        mfile = Drive.DriveApi.getFile(mGoogleApiClient, md.getDriveId()); 
                                        mfile.openContents(mGoogleApiClient, DriveFile.MODE_WRITE_ONLY, null).setResultCallback(writeToFile);
                                        return;
                                    }
                                }
                                openNewFile(res);
                            }
                        }
                    });
        }
    });
}

private ResultCallback<ContentsResult> readFromFile = new ResultCallback<ContentsResult>() {

    @Override
    public void onResult(ContentsResult result) {

        if (!result.getStatus().isSuccess()) {
            Log.v(TAG, "Error opening file");
            return;
        }
        try {
            db.close();//close database to make sure no open connections
            Contents content = result.getContents();
            InputStream is = content.getInputStream();
            BufferedInputStream in = new BufferedInputStream(is);
            FileOutputStream fos = new FileOutputStream(getDbPath());
            BufferedOutputStream out = new BufferedOutputStream(fos);

            byte[] buffer = new byte[8 * 1024];
            int n = 0;
            while( ( n = in.read(buffer) ) > 0 ) {
                out.write(buffer, 0, n);
            }

            in.close();
            out.flush();
            out.close();
            mfile.commitAndCloseContents(mGoogleApiClient, content).setResultCallback(new ResultCallback<Status>() {
                @Override
                public void onResult(Status result) {
                    showMessage("file done");
                    db = new MySQLiteHelper(context);
                }
            });
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
};

public void restoreDB(View v) {
    Drive.DriveApi.newContents(mGoogleApiClient).setResultCallback(new ResultCallback<ContentsResult>() {
        @Override
        public void onResult(ContentsResult result) {
            if (!result.getStatus().isSuccess()) {
                Log.v(TAG, "Error while trying to create new file contents");
                return;
            }
            final ContentsResult res = result;
            Query query = new Query.Builder().addFilter(Filters.eq(SearchableField.TITLE, DATABASE_NAME)).build();
            //TODO change this to appfolder search eventually
            Drive.DriveApi.query(mGoogleApiClient, query)
                    .setResultCallback(new ResultCallback<MetadataBufferResult>() {
                        @Override
                        public void onResult(MetadataBufferResult result) {
                            MetadataBuffer mdb = result.getMetadataBuffer();
                            if (mdb == null) {
                                showMessage("no file exists1");//TODO by string id
                            } else {
                                for (Metadata md : mdb) {
                                    if (!md.isTrashed()) {
                                        mfile = Drive.DriveApi.getFile(mGoogleApiClient, md.getDriveId());
                                        mfile.openContents(mGoogleApiClient, DriveFile.MODE_READ_ONLY, null).setResultCallback(readFromFile);
                                        showMessage("file done?");//TODO 
                                        return;
                                    }
                                }
                                showMessage("no file exists2");//TODO by string id
                            }
                        }
                    });
        }
    });
}

1 个答案:

答案 0 :(得分:0)

DriveFile mfile.commitAndCloseContents()不计入out.flush()的{​​{1}}和out.close()

你仍然必须冲洗并关闭。