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,提问作者조영민
相关产品推荐
相关产品推荐

