【问题标题】:Corrupted file is generated with FileInputStream and outstream : java, android使用 FileInputStream 和 outstream 生成损坏的文件:java、android
【发布时间】:2019-07-29 01:10:45
【问题描述】:

目前我正在使用流在我的应用程序中实现 SQlite 数据库备份功能。 当我备份数据库时它可以工作并且文件有数据,因为我已经通过“Db browser for SQlite”验证了它。但是,当尝试通过来自我的应用程序的数据库路径的 FilOuputStream 和通过 android SAF(存储访问框架)返回的 UrI 中的 InputStream 进行恢复时,指向我放置了数据库备份的外部存储,我得到损坏的数据库文件并且连接也关闭了。

以下是我为此目的使用的两种方法

备份

   //back db to a URI
public synchronized static boolean backupDb(Context context, Uri uri, String dbNam) throws IOException {
    File dbFile = new File(context.getDatabasePath(dbNam).getPath());
    FileInputStream inFilStream = new FileInputStream(dbFile);
    OutputStream outFilStream = context.getContentResolver().openOutputStream(uri);//new FileOutputStream(backupFile);
    byte[] buffer = new byte[1024];
    int length;
    while ((length = inFilStream.read(buffer)) > 0) {
        outFilStream.write(buffer, 0, length);
    }
    outFilStream.flush();
    outFilStream.close();
    inFilStream.close();
    return true;
}

恢复备份

  //restore db from a URI
public static synchronized boolean restoreBackup(Context context, Uri uri, String dbNam) {
    try {
        InputStream inFilStream = context.getContentResolver().openInputStream(uri);
        File dbFile = new File(context.getDatabasePath(dbNam).getPath());
        FileOutputStream outFilStream = new FileOutputStream(dbFile);
        byte[] buffer = new byte[1024];
        int length;
        while ((length = inFilStream.read(buffer)) > 0) {
            outFilStream.write(buffer, 0, length);
            Log.wtf("db", "restoring backup up");
        }
        outFilStream.flush(); 
     // using outFilStream.getFD().sync(); also not working
        outFilStream.close();
        inFilStream.close();
        return true;
    } catch (IOException e) {
        return false;
    }
}

日志

我不明白它为什么这样做,因为当我调试并将断点放在它工作的恢复方法中时,这很奇怪,请帮助找出那里出了什么问题。

【问题讨论】:

  • backupDbrestoreBackup 中的输入文件和输出文件的大小相同。 (只是 File.length())
  • 尝试复制并关闭应用程序。那么数据库是否有效?标头似乎是正确的,因为前 15 个字节是 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 根据Database File Format),所以可能是您遇到替换数据库和新数据库之间的冲突。或者,作为测试,恢复到不同的数据库名称,打开该数据库,看看你是否仍然遇到问题,如果没有,那么很确定替换和新的冲突(缓存数据)。
  • 如果数据库使用 WAL,另一个问题可能是 -shm 和或 -wal 文件有数据。更多关于这个here.

标签: java file-io android-sqlite inputstream outputstream


【解决方案1】:

循环丢失了一些字节,所以我使用 filechannel 之类的

    public synchronized static boolean saveDbBackup(Context context, Uri uri, String dbNam) throws IOException {
    File dbFile = new File(context.getDatabasePath(dbNam).getPath());
    FileChannel inFilChannel = new FileInputStream(dbFile).getChannel();
    FileChannel outFilChannel = ((FileOutputStream)context.getContentResolver().openOutputStream(uri)).getChannel();//new FileOutputStream(backupFile);
    outFilChannel.transferFrom(inFilChannel,0,inFilChannel.size());
    outFilChannel.close();
    inFilChannel.close();
    return true;
}

public static synchronized boolean restoreDbBackup(Context context, Uri uri, String dbNam) {
    try {
        FileChannel inFileChannel= ((FileInputStream) context.getContentResolver().openInputStream(uri)).getChannel();
        FileChannel outFileChannel= new FileOutputStream(new File(context.getDatabasePath(dbNam).getPath())).getChannel();
        outFileChannel.transferFrom(inFileChannel,0,inFileChannel.size());
        outFilChannel.close();
        inFilChannel.close();
        return true;
    } catch (IOException e) {
        return false;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-18
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多