Android读取用户选择的CSV文件并存储到变量的实现方案
问题解决:读取用户选择的CSV文件并更新TextView
原代码的核心问题:
- 废弃API未替换:使用
startActivity()而非新的Activity Result API,导致onActivityResult()完全不会被触发 - 文件读取逻辑错误:尝试用
resources.assets.open()打开用户选择的文件URI,这是错误的——assets目录是应用内置资源,用户选择的文件属于外部存储/其他应用内容,必须通过ContentResolver访问 - 未注册结果回调:没有为文件选择请求绑定正确的回调,所以选择文件后没有任何响应
修正方案(使用Activity Result API)
AndroidX推荐用ActivityResultContracts.GetContent()替代旧的ACTION_GET_CONTENT + onActivityResult流程,以下是完整修正后的代码:
修正后的ContentFragment.kt
package com.example.myapplication import android.net.Uri import android.os.Bundle import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.result.contract.ActivityResultContracts import com.example.myapplication.databinding.FragmentContentBinding import java.io.BufferedReader import java.io.InputStreamReader class ContentFragment : Fragment() { private var _binding: FragmentContentBinding? = null private val binding get() = _binding!! // 注册文件选择的回调 private val pickFileLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> uri?.let { readFileContent(it) } } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { _binding = FragmentContentBinding.inflate(inflater, container, false) // 保留你的asset文件测试逻辑 val assetFile = BufferedReader(InputStreamReader(resources.assets.open("Testfile.csv"))).use { it.readText() } binding.TestButton.setOnClickListener { // 启动文件选择器,指定只选csv文件更精准 pickFileLauncher.launch("text/csv") // 若需要支持所有文件类型,可替换为"*/*" // pickFileLauncher.launch("*/*") } return binding.root } // 读取指定URI的文件内容并更新TextView private fun readFileContent(uri: Uri) { requireContext().contentResolver.openInputStream(uri)?.use { inputStream -> val fileContent = BufferedReader(InputStreamReader(inputStream)).use { it.readText() } binding.fileContent.text = fileContent } } override fun onDestroyView() { super.onDestroyView() _binding = null // 避免内存泄漏 } }
关键修改说明:
- 替换废弃API:用
registerForActivityResult(ActivityResultContracts.GetContent())注册回调,彻底替代旧的startActivityForResult和onActivityResult - 正确读取文件:通过
requireContext().contentResolver.openInputStream(uri)获取用户选择文件的输入流,这是访问外部/其他应用文件的标准方式 - 精准筛选文件:启动选择器时指定
"text/csv",避免用户选择非CSV文件(可根据需求调整) - 内存泄漏防护:在
onDestroyView中置空_binding,符合View Binding的最佳实践
其他注意事项:
- 无需修改
MainActivity.kt和布局文件,保持原样即可 - 适配Android 13+时,不需要额外申请存储权限——
ACTION_GET_CONTENT通过Content Provider访问文件,无需读写外部存储权限 - 若处理大文件,建议用协程异步读取,避免阻塞主线程
内容的提问来源于stack exchange,提问作者owmal
相关产品推荐
相关产品推荐

