SQLiteデータベースをcsvファイルにエクスポートするために利用できるチュートリアルはたくさんありますが、部屋のデータベースからエクスポートするには十分なものがありません。
Sqliteエクスポートリファレンスの使用 AndroidでSQLiteデータベースをcsvファイルにエクスポート 行の各列を手動で解析してスペースを確保します。以下は私のコードです:
@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をエクスポートする他の方法はありますか?部屋でもテーブルの列名を実用的に取得していないため、すべてのテーブルに動的に共通のロジックを作成することはできません。
これを試してください
カーソルから列データを取得
@Query("SELECT * FROM Category")
Cursor getAllCategory();
これはあなたが探している答えかもしれません。
リンク: https://stackoverflow.com/a/49133574/9994604
それを行う手動の方法もあります。データベースのエクスポート、
リンク: https://stackoverflow.com/a/6542214/9994604
Sqliteブラウザで開く: https://sqlitebrowser.org (無料)
CSV/JSON、SQLで好きなようにエクスポートします。
大規模なRoomデータベースを反復処理しようとした方法は2つあります。
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()
関数は、pagedList
またはFlowable
内にLiveData
を返します。 setEnablePlaceholders(true)
を設定したので、_pagedList.size
_は、メモリにない場合でも全体のサイズを表示します。したがって、pageSize
が50で、すべてのデータサイズが1000の場合、_pagedList.size
_は1000を返しますが、それらのほとんどはnullになります。次のページを照会して処理するには:
_// 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分かかります。
ルームデータベースデータを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()
}
}
}
}