请求Kotlin实现PDF文件存入SQLite数据库(BLOB方式)的示例代码
在Android Kotlin中实现PDF文件存入SQLite数据库(BLOB方式)
一、配置Room数据库(推荐使用,替代原生SQLite)
首先添加Room依赖到build.gradle(Module级别):
dependencies { def room_version = "2.5.0" implementation "androidx.room:room-runtime:$room_version" kapt "androidx.room:room-compiler:$room_version" // Kotlin扩展支持 implementation "androidx.room:room-ktx:$room_version" }
1. 创建实体类(对应数据库表)
import androidx.room.Entity import androidx.room.PrimaryKey @Entity(tableName = "pdf_files") data class PdfFile( @PrimaryKey(autoGenerate = true) val id: Int = 0, val fileName: String, // 用于区分不同PDF文件 val pdfBlob: ByteArray // 存储PDF的字节数组 ) { // 重写equals和hashCode,解决ByteArray默认比较引用的问题 override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false other as PdfFile if (id != other.id) return false if (fileName != other.fileName) return false if (!pdfBlob.contentEquals(other.pdfBlob)) return false return true } override fun hashCode(): Int { var result = id result = 31 * result + fileName.hashCode() result = 31 * result + pdfBlob.contentHashCode() return result } }
2. 创建Dao接口
import androidx.room.Dao import androidx.room.Insert import androidx.room.Query @Dao interface PdfFileDao { @Insert suspend fun insertPdf(pdfFile: PdfFile) @Query("SELECT * FROM pdf_files WHERE fileName = :name") suspend fun getPdfByName(name: String): PdfFile? }
3. 创建数据库实例
import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase import android.content.Context @Database(entities = [PdfFile::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun pdfFileDao(): PdfFileDao companion object { // 单例模式避免重复创建数据库实例 @Volatile private var INSTANCE: AppDatabase? = null fun getDatabase(context: Context): AppDatabase { return INSTANCE ?: synchronized(this) { val instance = Room.databaseBuilder( context.applicationContext, AppDatabase::class.java, "app_database" ).build() INSTANCE = instance instance } } } }
二、将Assets中的PDF转为字节数组
把你的PDF文件放在src/main/assets目录下,用以下方法读取为ByteArray:
import android.content.Context import java.io.ByteArrayOutputStream import java.io.IOException fun getPdfFromAssets(context: Context, fileName: String): ByteArray? { return try { context.assets.open(fileName).use { inputStream -> ByteArrayOutputStream().use { outputStream -> val buffer = ByteArray(1024) var length: Int while (inputStream.read(buffer).also { length = it } != -1) { outputStream.write(buffer, 0, length) } outputStream.toByteArray() } } } catch (e: IOException) { e.printStackTrace() null } }
三、插入PDF到数据库
在协程中执行数据库操作(避免主线程阻塞):
import android.content.Context import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch fun insertPdfIntoDatabase(context: Context, fileName: String) { val pdfBytes = getPdfFromAssets(context, fileName) ?: return val pdfFile = PdfFile(fileName = fileName, pdfBlob = pdfBytes) GlobalScope.launch(Dispatchers.IO) { val db = AppDatabase.getDatabase(context) db.pdfFileDao().insertPdf(pdfFile) } }
四、从数据库读取PDF并使用
读取后可写入临时文件,再用第三方PDFView打开(以com.github.barteksc:android-pdf-viewer为例):
import android.content.Context import android.os.Environment import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File import java.io.FileOutputStream fun readPdfFromDatabase(context: Context, fileName: String, onPdfReady: (File?) -> Unit) { GlobalScope.launch(Dispatchers.IO) { val db = AppDatabase.getDatabase(context) val pdfFile = db.pdfFileDao().getPdfByName(fileName) ?: run { withContext(Dispatchers.Main) { onPdfReady(null) } return@launch } // 创建临时文件存储读取到的PDF val tempFile = File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), fileName) try { FileOutputStream(tempFile).use { outputStream -> outputStream.write(pdfFile.pdfBlob) } withContext(Dispatchers.Main) { onPdfReady(tempFile) } } catch (e: Exception) { e.printStackTrace() withContext(Dispatchers.Main) { onPdfReady(null) } } } }
五、注意事项
- 文件大小限制:SQLite支持最大1GB的BLOB,但大体积PDF会显著降低数据库性能,建议只存储几MB以内的小文件。
- 主线程操作:所有数据库操作必须在子线程执行,这里用协程
Dispatchers.IO处理,避免ANR。 - APK体积:将PDF打包进APK会增加安装包大小,若存在多个大文件,建议权衡是否改用在线下载+本地存储路径的方案。
内容的提问来源于stack exchange,提问作者Whitt
相关产品推荐
相关产品推荐

