Kotlin安卓:SQLite导出数据至TXT文件为空问题求助
联系人APP导出/导入TXT功能修复方案
问题分析
当前导出功能存在两个核心问题:
- 数据格式错误:
dataToWriteInFile()直接调用getContactsList().toString(),会生成带方括号、逗号分隔的List字符串,不符合每行一个联系人、分号分隔字段的要求。 - 原文件写入逻辑错误:最初代码尝试用
File处理Content URI,违反Android文件系统规范;更新后的写入逻辑方向正确,但数据生成错误导致文件内容异常。
修复步骤
1. 修正数据生成逻辑
修改dataToWriteInFile()方法,遍历联系人列表,将每个联系人的格式化字符串(已通过ContactModelClass.toString()实现分号分隔)逐行写入StringBuilder:
private fun dataToWriteInFile(): String { val stringBuilder = StringBuilder() getContactsList().forEach { contact -> stringBuilder.appendLine(contact.toString()) } return stringBuilder.toString() }
2. 优化文件写入逻辑(确保稳定性)
简化更新后的写入逻辑,去除冗余判断,利用Kotlin的use函数自动关闭流:
private val createFile = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { result.data?.data?.let { uri -> try { contentResolver.openOutputStream(uri)?.use { outputStream -> outputStream.writer().use { writer -> writer.write(dataToWriteInFile()) } } } catch (e: IOException) { e.printStackTrace() // 可添加Toast提示用户导出失败 } } } }
3. 实现TXT导入功能
添加导入逻辑,调用文件选择器读取TXT文件,解析每行内容并插入SQLite:
3.1 注册文件选择器
在ContactListActivity中添加导入用的ActivityResultContract:
private val pickFile = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { result.data?.data?.let { uri -> try { contentResolver.openInputStream(uri)?.use { inputStream -> inputStream.bufferedReader().useLines { lines -> val sqliteHelper = SQLiteHelper(this) // 可选:导入前清空现有数据,根据需求调整 // sqliteHelper.deleteContactsTable() lines.forEach { line -> val fields = line.split(";") if (fields.size == 9) { // 校验字段数量匹配 val contact = ContactModelClass( id = fields[0].toInt(), name = fields[1], surname = fields[2], dateOfBirth = fields[3], phoneNumber = fields[4], email = fields[5], address = fields[6], city = fields[7], notes = fields[8] ) sqliteHelper.insertContact(contact) } } // 导入完成后刷新RecyclerView setupListOfDataIntoRecyclerView() } } } catch (e: IOException) { e.printStackTrace() // Toast提示导入失败 } catch (e: NumberFormatException) { e.printStackTrace() // Toast提示文件格式错误 } } } }
3.2 添加导入按钮点击事件
在onCreate中绑定导入按钮(需先在布局中添加对应按钮):
// 假设布局中按钮id为importDataButton val importDataButton = findViewById<Button>(R.id.importDataButton) importDataButton.setOnClickListener { val pickFileIntent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = "text/plain" } pickFile.launch(pickFileIntent) }
关键说明
ContactModelClass的toString()方法已正确实现字段分号分隔,无需修改。- 导出/导入均使用Android Content URI机制,符合现代Android文件访问规范,可直接访问下载文件夹等外部存储位置。
- 导入时添加了字段校验和异常捕获,避免因文件格式错误导致崩溃。
内容的提问来源于stack exchange,提问作者MyrsiniStas
相关产品推荐
相关产品推荐

