数据库读取异常 SQLiteBlobTooBigException 解决方案

SQLiteBlobTooBigException 异常发生在读数据库信息的时候,由于读取的数据超过了CursorWindow最大额度(2mb) 的限制,导致抛出异常。因为数据库增删改查操作是基础库封装,无法直接修改,所以采取了文件迁移的解决方案 sqlite ---> file。

整体的解决方案有:

  1. 查询时使用 substr 函数做分批查询。缺点 : 如果查询的时 json 字符串,无法使用使用此方法
  2. 文件迁移。保存的文本由数据库存储迁移到文件存储。
  3. 修改 CursorWindow 最大限度 (没找到怎么修改,不知道有没有现在风险)。
  4. 数据库存储文件路径,查询、插入时候通过路径插入到文件存储,和方案二基本类似。

使用文件迁移方案的话仅需要数据库读写地方做一个判断。

  1. 插入时: 全部写入文件
  2. 读取时: 如果文件存在优先读文件,文件不存在则读数据库(兼容覆盖安装升级的场景)
  3. 在插入前: 如果文件不存在,则删除原数据库数据,之后再将新数据写入文件,这样就不会有两份数据存在了。

附文件存储代码如下:

fun writeTxtToFile(strContent: String, filePath: String, fileName: String) {
        makeFilePath(filePath, fileName)
        val strFilePath = filePath + fileName
        val file = File(strFilePath)
        var raf: FileOutputStream? = null
        try {
            if (!file.exists()) {
                file.parentFile.mkdirs()
                file.createNewFile()
            }
            raf = FileOutputStream(file) // 这里也可以改造成追加存储
            raf.write(strContent.toByteArray())
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            try {
                raf?.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

private fun makeFilePath(filePath: String, fileName: String): File? {
        var file: File? = null
        makeRootDirectory(filePath)
        try {
            file = File(filePath + fileName)
            if (!file.exists()) {
                file.createNewFile()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return file
    }

    private fun makeRootDirectory(filePath: String) {
        var file: File? = null
        try {
            file = File(filePath)
            if (!file.exists()) {
                file.mkdir()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
/**
 * 读取文件信息
 */
open fun readTxtFile(filePath: String, fileName: String): String {
    val file = File(filePath, fileName)
    var bufferedReader: BufferedReader? = null
    val stringBuffer = StringBuffer()
    try {
        var readline = ""
        bufferedReader = BufferedReader(FileReader(file))
        while (bufferedReader.readLine()?.also { readline = it } != null) {
            stringBuffer.append(readline)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        try {
            bufferedReader?.close()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    return stringBuffer.toString()
}

/**
 * 文件是否存在
 */
fun isFileExist(path: String): Boolean {
    val file = File(path)
    return file.exists()
}

你可能感兴趣的:(数据库读取异常 SQLiteBlobTooBigException 解决方案)