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

Kotlin读取外部存储文本文件报错:路径分隔符异常求解

解决Android Kotlin读取外部存储文本文件报错问题

错误根源

你遇到的java.lang.IllegalArgumentException是因为**openFileInput()方法只能接收应用内部存储的文件名**,不能直接传入content://开头的内容URI。通过ACTION_OPEN_DOCUMENT获取的是系统提供的内容URI,必须用ContentResolver来读取,而不是openFileInput。

分步解决

1. 替换文件读取方式

在onActivityResult中,把错误的openFileInput(uri.toString())替换为通过contentResolver打开输入流,修改后的代码如下:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    if (requestCode == getTextCode && resultCode == Activity.RESULT_OK) {
        try{
            data?.data?.also { uri ->
                Toast.makeText(this, uri.toString(), Toast.LENGTH_SHORT).show()
                Log.d("test", uri.toString())
                // 通过ContentResolver读取文件流
                contentResolver.openInputStream(uri)?.bufferedReader()?.useLines { lines ->
                    lines.forEach { line ->
                        Log.d("test", line)
                    }
                }
            }
        }catch(err:Exception){
            Log.d("test", err.toString())
        }
    }
}

2. 修正初始化URI的错误

你初始化的downUri是普通文件路径,不符合SAF(存储访问框架)的Tree URI要求,会导致文件选择器初始化异常。替换为正确的Tree URI:

vBinding.getFromTxt.setOnClickListener {
    // 构建Documents目录的合法Tree URI
    val downUri = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3ADocuments")
    openFile(downUri)
}

3. 添加动态权限申请(Android 6.0+必备)

静态权限声明不足以在Android 6.0及以上系统获得读取权限,需要在代码中动态申请:

override fun onCreate(savedInstanceState: Bundle?) {
    val vBinding = ActivityMainBinding.inflate(layoutInflater)
    super.onCreate(savedInstanceState)
    setContentView(vBinding.root)

    // 动态申请读取外部存储权限
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(
            this,
            arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
            1001 // 自定义权限请求码
        )
    }

    vBinding.getFromTxt.setOnClickListener {
        val downUri = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3ADocuments")
        openFile(downUri)
    }
}

// 处理权限申请结果
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == 1001) {
        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 权限申请成功,可执行文件操作
        } else {
            Toast.makeText(this, "需要读取权限才能访问文件", Toast.LENGTH_SHORT).show()
        }
    }
}

Manifest配置补充说明

  • 你已添加的READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限是正确的,Android 13+读取文本文件仍可使用READ_EXTERNAL_STORAGE,无需额外申请媒体权限。
  • android:requestLegacyExternalStorage="true"仅对Android 10(API 29)生效,使用SAF框架时该配置可保留但非必需。

内容的提问来源于stack exchange,提问作者조영민

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:16:12