在android中将房间数据库导出到csv文件
Posted
技术标签:
【中文标题】在android中将房间数据库导出到csv文件【英文标题】:Exporting Room Database to csv file in android 【发布时间】:2018-12-05 21:37:26 【问题描述】:有很多教程可用于将 SQLite 数据库导出到 csv 文件,但从房间数据库导出的内容还不够。
使用 sqlite 导出引用 Exporting SQLite Database to csv file in android 手动解析行的每一列以获得空间。以下是我的代码:
@Dao
interface CategoryDao
@Query("SELECT * FROM Category")
fun getAllCategory(): List<Category>
// Export csv logic
val categoryList = categoryDao.getAllCategory()
val csvWrite = CSVWriter(FileWriter(file))
for (item in categoryList)
val arrStr = arrayOf<String>(item.categoryId, item.categoryName)
csvWrite.writeNext(arrStr)
还有其他导出csv的方法吗?即使在房间里也没有实用地获取表的列名,因此无法为所有表创建动态的通用逻辑。
【问题讨论】:
房间数据库是sqlite数据库——没有区别 您可以使用 Jackson CSV 库将 Room 类映射到文件中 【参考方案1】:试试这个 从 Cursor 中获取 Column 数据
@Query("SELECT * FROM Category")
Cursor getAllCategory();
【讨论】:
【参考方案2】:要将房间数据库数据导出到mydb.sqlite
文件并存储到外部存储中,请按照以下步骤操作。
fun exportDatabase()
val sd = Environment.getExternalStorageDirectory()
// Get the Room database storage path using SupportSQLiteOpenHelper
AppDatabase.getDatabase(applicationContext)!!.openHelper.writableDatabase.path
if (sd.canWrite())
val currentDBPath = AppDatabase.getDatabase(applicationContext)!!.openHelper.writableDatabase.path
val backupDBPath = "mydb.sqlite" //you can modify the file type you need to export
val currentDB = File(currentDBPath)
val backupDB = File(sd, backupDBPath)
if (currentDB.exists())
try
val src = FileInputStream(currentDB).channel
val dst = FileOutputStream(backupDB).channel
dst.transferFrom(src, 0, src.size())
src.close()
dst.close()
catch (e: IOException)
e.printStackTrace()
【讨论】:
【参考方案3】:我尝试通过两种方式迭代大型 Room 数据库:
1- 获取 Cursor
并对其进行迭代:
import android.database.Cursor
...
@Query("SELECT * FROM Category")
fun getAllCategory(): Cursor<Category>
...
val success = cursor.moveToFirst()
if (success)
while (!cursor.isAfterLast)
// Process items
cursor.moveToNext()
else
// Empty
cursor.close()
2- 使用PagedList
一次获取pageSize 数量的项目并进行处理。然后查询另一个页面并处理:
@Query("SELECT * FROM Category")
fun getAllCategory(): DataSource.Factory<Int, Category>
// Here i will return Flowable. You can return LiveData with 'LivePagedListBuilder'
fun getCategories(pageSize: Int): Flowable<PagedList<Category>>
val config = PagedList.Config.Builder()
.setPageSize(pageSize)
.setPrefetchDistance(pageSize / 4)
.setEnablePlaceholders(true)
.setInitialLoadSizeHint(pageSize)
.build()
return RxPagedListBuilder(categoryDao.getAllCategory(), config)
.buildFlowable(BackpressureStrategy.BUFFER)
现在上面的getCategories()
函数将在Flowable
或LiveData
内返回pagedList
。由于我们设置了setEnablePlaceholders(true)
,pagedList.size
将显示整个大小,即使它不在内存中。因此,如果pageSize
为 50,并且所有数据大小为 1000,pagedList.size
将返回 1000,但其中大部分为空。查询下一页并处理:
// Callback is triggered when next page is loaded
pagedList.addWeakCallback(pagedList.snapshot(), object : PagedList.Callback()
override fun onChanged(position: Int, count: Int)
for (index in position until (position + count))
if (index == (position + count - 1))
if (index < (pagedList.size - 1))
pagedList.loadAround(index + 1)
else
// Last item is processed.
else
processCurrentValue(index, pagedList[index]!!)
override fun onInserted(position: Int, count: Int)
// You better not change database while iterating over it
override fun onRemoved(position: Int, count: Int)
// You better not change database while iterating over it
)
// Start to iterate and query next page when item is null.
for (index in 0 until pagedList.size)
if (pagedList[index] != null)
processCurrentValue(index, pagedList[index]!!)
else
// Query next page
pagedList.loadAround(index)
break
结论:在PagedList
方法中,您可以一次获取数千行并进行处理,而在Cursor
方法中,您可以逐行迭代。当pageSize > 3000时我发现PagedList
不稳定。它有时不返回页面。所以我使用了Cursor
。在 Android 8 手机上使用这两种方法迭代(和处理)900k 行大约需要 5 分钟。
【讨论】:
问题是关于导出数据库而不是关于如何使用分页库! 它是关于通过迭代表的overvrows来导出数据库。因为您可能会在导出时转换数据。导出不仅意味着转储数据库并从中创建包含所有内容的文件以上是关于在android中将房间数据库导出到csv文件的主要内容,如果未能解决你的问题,请参考以下文章
在 SQL Server 2008 中将查询结果导出到 .csv 文件
如何:在 MySQL 工作台中将记录集导出为分号分隔的 csv 文件?