我有一个大约150mb的大型数据库。我是否可以将压缩版本的数据库(例如zip )放在资产文件夹中以供空间使用,或者这是不可能的吗?
PS: android studio的apk压缩是不够的
发布于 2021-06-20 02:43:31
首先,您需要一个函数,它可以将归档文件解压缩到某个目录:
// unzip(new File("/sdcard/whatToUnzip.zip"), new File("/toThisFolder"));
fun unzip(zipFile: File, targetDirectory: File) {
unzip(BufferedInputStream(FileInputStream(zipFile)), targetDirectory)
}
fun unzip(zipInputStream: InputStream, targetDirectory: File) {
try {//BufferedInputStream(zipFileStream)
ZipInputStream(zipInputStream).use { zipInput ->
var zipEntry: ZipEntry
var count: Int
val buffer = ByteArray(65536)
while (zipInput.nextEntry.also { zipEntry = it } != null) {
val file = File(targetDirectory, zipEntry.name)
val dir: File? = if (zipEntry.isDirectory) file else file.parentFile
if (dir != null && !dir.isDirectory && !dir.mkdirs()) throw FileNotFoundException(
"Failed to ensure directory: " + dir.absolutePath
)
if (zipEntry.isDirectory) continue
FileOutputStream(file).use { fileOutput ->
while (zipInput.read(buffer).also { count = it } != -1) fileOutput.write(
buffer,
0,
count
)
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}我是从that stackoverflow's thread.获取的,请阅读一个帖子以获取更多详细信息。然后,我添加了两个方法来处理app资产文件夹中的文件:
fun unzipAsset(assetsFilePath: String, context: Context, targetDirectory: File) {
unzip(context.assets.open(assetsFilePath), targetDirectory)
}
fun Context.unzipAsset(assetsFilePath: String, targetDirectory: File) = unzipAsset(
assetsFilePath,
this,
targetDirectory
)现在我们可以将文件解压缩到文件夹中。当我使用Room.databaseBuilder的createFromAsset或createFromFile方法时,为了避免按房间复制解压缩的数据库文件,我想将文件解压缩到空间用来存储数据库文件的应用程序databases文件夹中。这就是为什么我需要其他方法来获取db文件夹路径并检查db文件何时已经存在:
fun Context.databaseFolderPath(): File? = this.getDatabasePath("any.db").parentFile
// name – The name of the database file.
fun Context.isRoomDbFileExist(name: String): Boolean {
return this.getDatabasePath(name)?.exists() ?: false
}现在,如何一起使用all thinks:
abstract class AppDatabase : RoomDatabase() {
companion object {
private const val DB_NAME = "sunflower-db"
// Create and pre-populate the database. See this article for more details:
// https://medium.com/google-developers/7-pro-tips-for-room-fbadea4bfbd1#4785
private fun buildDatabase(context: Context): AppDatabase {
if(!context.isRoomDbFileExist(DB_NAME)) {
// unzip db file to app's databases directory to avoid copy of unzipped file by room
context.unzipAsset("sunflower-db.zip", context.databaseFolderPath()!!)
// or unzip(File("your file"), context.databaseFolderPath()!!)
}
return Room.databaseBuilder(context, AppDatabase::class.java, DB_NAME)
//.createFromAsset(DB_NAME) // not zipped db file
.build()
}
}
}我在nice open source project - sunflower上测试了这段代码。接下来,我想显示带有项目结构的屏幕,其中sunflower-db.zip位于:

上面的方法是可行的,但是你不应该把这个样本看作是正确的或者最佳的解决方案。你应该考虑避免从主线程解压缩进程。如果你实现自己的SupportSQLiteOpenHelper.Factory(看起来很复杂),可能会更好。
https://stackoverflow.com/questions/68031876
复制相似问题