是否可以压缩房间持久性库的预打包数据库?
Is it possible to compress a prepackaged database for room persistence library?
我有一个大约 150mb 的巨大数据库。我可以把数据库的压缩版本例如将 zip 压缩到 asset 文件夹中供房间使用还是不可能?
PS: android studio apk 压缩不够
首先你需要一个可以将压缩包解压到某个目录的函数:
// 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 Whosebug's thread. 中得到它 请阅读线程以获取更多详细信息。然后我添加了两种方法来处理应用程序资产文件夹中的文件:
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
)
现在我们可以解压文件到文件夹了。为避免在使用 createFromAsset
或 Room.databaseBuilder
的 createFromFile 方法时按房间复制解压缩的数据库文件,我想将文件解压缩到房间用于存储数据库文件的应用程序 databases
文件夹。这就是为什么我需要其他方法来获取数据库文件夹路径并检查数据库文件何时存在的原因:
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
}
现在,如何综合运用所有想法:
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
(看起来很复杂)可能会更好。
我有一个大约 150mb 的巨大数据库。我可以把数据库的压缩版本例如将 zip 压缩到 asset 文件夹中供房间使用还是不可能?
PS: android studio apk 压缩不够
首先你需要一个可以将压缩包解压到某个目录的函数:
// 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 Whosebug's thread. 中得到它 请阅读线程以获取更多详细信息。然后我添加了两种方法来处理应用程序资产文件夹中的文件:
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
)
现在我们可以解压文件到文件夹了。为避免在使用 createFromAsset
或 Room.databaseBuilder
的 createFromFile 方法时按房间复制解压缩的数据库文件,我想将文件解压缩到房间用于存储数据库文件的应用程序 databases
文件夹。这就是为什么我需要其他方法来获取数据库文件夹路径并检查数据库文件何时存在的原因:
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
}
现在,如何综合运用所有想法:
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
(看起来很复杂)可能会更好。