【发布时间】:2023-01-13 00:09:33
【问题描述】:
如何将我的房间数据库导出到 .CSV 文件。我希望将其保存到设备存储中。我搜索了所有内容,但没有合适的答案。我希望有办法解决这个问题。
【问题讨论】:
标签: android database csv kotlin android-room
如何将我的房间数据库导出到 .CSV 文件。我希望将其保存到设备存储中。我搜索了所有内容,但没有合适的答案。我希望有办法解决这个问题。
【问题讨论】:
标签: android database csv kotlin android-room
您不能只将数据库另存为 CSV。但是,如果完全检查点,数据库只是一个文件。如果没有完全检查点,那么它将是三个文件(除非禁用了预写日志记录)。
数据库本身由多个部分组成,一个标题(文件的前 100 个字节),然后是各个组件的数据块。其中大部分依赖于模式(表),也有系统表
将所有数据保存为 CSV 文件会很复杂(而且不需要,因为您只需复制数据库文件即可)。
如果您想要的是应用程序数据的 CSV,那将取决于表格。如果您是单个表,那么将数据提取为 CSV 会相对简单,但如果数据包含逗号,则可能会很复杂。
如果有多个表,则必须区分表的数据。
同样最简单的方法,如果只是保护数据就是复制文件。
然而,作为基于的示例:-
有 3 个表的数据库(除了系统表)
然后:-
@Dao 注释接口(即 AllDao)中的以下内容:-
@Query("SELECT postId||','||content FROM postDataLocal")
fun getPostDataLocalCSV(): List<String>
@Query("SELECT groupPostIdMap||','||groupId||','||groupName FROM groupDataLocal")
fun getGroupDataLocalCSV(): List<String>
@Query("SELECT adminGroupIdMap||','||userId||','||adminName||','||avatar FROM adminDataLocal")
fun getAdminDataLocalCSV(): List<String>
以及以下函数,其中 dao 是先前实例化的 AllDao 实例:-
private fun createCSV() {
val sb = StringBuilder()
var afterFirst = false
sb.append("{POSTDATALOCAL}")
for (s in dao.getPostDataLocalCSV()) {
if(afterFirst) sb.append(",")
afterFirst = true
sb.append(s)
}
afterFirst = false
sb.append("{GROUPDATALOCAL}")
for (s in dao.getGroupDataLocalCSV()) {
if (afterFirst) sb.append(",")
afterFirst = true
sb.append(s)
}
afterFirst = false
sb.append("{ADMINDATALOCAL}")
for (s in dao.getAdminDataLocalCSV()) {
if ((afterFirst)) sb.append(",")
afterFirst = true
sb.append(s)
}
Log.d("CSV_DATA","CSV is :-
$sb")
}
然后在一个活动中(dao 已被实例化)以下内容:-
createCSV()
然后,当数据库包含以下数据(通过 App Inspection 提取)时:-
PostDataLocal
组数据本地
AdminDataLocal
写入日志的结果(可以写入文件而不是日志)是:-
D/CSV_DATA: CSV is :-
{POSTDATALOCAL}1,Post001,2,Post002,3,Post003{GROUPDATALOCAL}1,1,Group001 (Post001),1,2,Group002 (Post001),1,3,Group003 (Post001),2,4,Group004 (Post002),2,5,Group005 (Post002),3,6,Group006 (Post003){ADMINDATALOCAL}1,1,Admin001,admin001.gif,1,2,Admin002,admin002.gif,1,3,Admin003,admin003.gif,2,4,Admin004,admin004.gif,2,5,Admin005,admin005.gif,3,6,Admin006,admin006.gif,4,7,Admin007,admin007.gif,5,8,Admin008,admin008.gif,6,9,Admin009,admin009.gif,6,10,Admin010,admin010.gif
额外的
这是一个更自动化的版本,您不需要在其中创建带 @Query 注释的函数,而是询问 sqlite_master 以提取表并使用 table_info pragma 来确定列,从而构建相应的 SQL。
因此,它应该适合任何 Room 数据库。
它还允许将数据中的逗号替换为逗号指示符,然后在处理 CSV 时可以将其替换。
支持(次要/由主要调用)功能是:-
private fun getTableColumnNames(tableName: String, suppDB: SupportSQLiteDatabase): List<String> {
val rv = arrayListOf<String>()
val csr = suppDB.query("SELECT name FROM pragma_table_info('${tableName}')",null)
while (csr.moveToNext()) {
rv.add(csr.getString(0))
}
csr.close()
return rv.toList()
}
和主要功能:-
private fun AutoCreateCSV(): String {
val replaceCommaInData = "{COMMA}" /* commas in the data will be replaced by this */
val rv = StringBuilder()
val sql = StringBuilder()
var afterFirstTable = false
var afterFirstColumn = false
var afterFirstRow = false
val suppDb = db.getOpenHelper().writableDatabase
var currentTableName: String = ""
val csr = db.query("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE('sqlite_%') AND name NOT LIKE('room_%') AND name NOT LIKE('android_%')", null)
while (csr.moveToNext()) {
sql.clear()
sql.append("SELECT ")
currentTableName = csr.getString(0)
if (afterFirstTable) rv.append(",")
afterFirstTable = true
afterFirstColumn = false
rv.append("{$currentTableName},")
for (columnName in getTableColumnNames(currentTableName,suppDb)) {
if (afterFirstColumn) sql.append("||','||")
afterFirstColumn = true
sql.append("replace(`$columnName`,',','$replaceCommaInData')")
}
sql.append(" FROM `${currentTableName}`")
val csr2 = db.query(sql.toString(),null)
afterFirstRow = false
while (csr2.moveToNext()) {
if (afterFirstRow) rv.append(",")
afterFirstRow = true
rv.append(csr2.getString(0))
}
csr2.close()
}
csr.close()
return rv.toString()
}
使用相同的数据并作为主要函数返回一个字符串,以下代码 Log.d("CSV_DATA2",AutoCreateCSV()) 导致:-
D/CSV_DATA2: {PostDataLocal},1,Post001,2,Post002,3,Post003,{GroupDataLocal},1,1,Group001 (Post001),1,2,Group002 (Post001),1,3,Group003 (Post001),2,4,Group004 (Post002),2,5,Group005 (Post002),3,6,Group006 (Post003),{AdminDataLocal},1,1,Admin001,admin001.gif,1,2,Admin002,admin002.gif,1,3,Admin003,admin003.gif,2,4,Admin004,admin004.gif,2,5,Admin005,admin005.gif,3,6,Admin006,admin006.gif,4,7,Admin007,admin007.gif,5,8,Admin008,admin008.gif,6,9,Admin009,admin009.gif,6,10,Admin010,admin010.gif
如果数据包含逗号,例如post001 更改为值Post001, <<note the comma in the data>>
然后 :-
D/CSV_DATA2: {PostDataLocal},1,Post001{COMMA} <<note the comma in the data>>,2,Post002,3 ....
【讨论】:
从房间获取所有数据作为列表并使用此库 https://github.com/doyaaaaaken/kotlin-csv
【讨论】: