You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android读取用户选择的CSV文件并存储到变量的实现方案

问题解决:读取用户选择的CSV文件并更新TextView

原代码的核心问题:

  1. 废弃API未替换:使用startActivity()而非新的Activity Result API,导致onActivityResult()完全不会被触发
  2. 文件读取逻辑错误:尝试用resources.assets.open()打开用户选择的文件URI,这是错误的——assets目录是应用内置资源,用户选择的文件属于外部存储/其他应用内容,必须通过ContentResolver访问
  3. 未注册结果回调:没有为文件选择请求绑定正确的回调,所以选择文件后没有任何响应

修正方案(使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 16:20:47