求助:在Kotlin Jetpack Compose中使用rememberLauncherForActivityResult读取文件时出现文件不存在错误
问题分析与解决方案
嘿,这个问题我之前踩过坑!你出错的核心原因是把content URI当成了本地文件路径来处理——这是Android存储访问框架(SAF)里非常常见的误区。
为什么会报错?
当你用Intent.ACTION_OPEN_DOCUMENT选择文件时,系统返回的uri是content://开头的内容URI,这是Android内容提供者(Content Provider)对外暴露的文件访问入口,并不是直接的本地文件系统路径。你直接把它传给File(uri),系统自然找不到对应的文件,因为这个“路径”在本地文件系统里根本不存在,所以才会抛出ENOENT (No such file or directory)错误。
正确的处理方式
要读取这个URI对应的文件内容,你需要通过ContentResolver来打开输入流,而不是直接操作File。下面是修改后的完整代码:
@Composable private fun Screen() { val context = LocalContext.current val launcher = rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { result -> val uri = result.data?.data uri?.let { contentUri -> // 使用ContentResolver打开输入流读取文件,异步执行避免阻塞主线程 lifecycleScope.launch { try { context.contentResolver.openInputStream(contentUri)?.use { inputStream -> val bytes = inputStream.readBytes() println("文件读取完成,字节数:${bytes.size}") } } catch (e: IOException) { e.printStackTrace() // 这里可以添加用户友好的错误提示,比如Toast } } } } Column() { Button(onClick = { val intent = Intent().setType("*/*").setAction(Intent.ACTION_OPEN_DOCUMENT) launcher.launch(intent) }) { Text("Open file") } } }
额外注意点
- 我添加了
lifecycleScope.launch来异步读取文件,避免读取大文件时阻塞UI主线程(会导致ANR)。 - 使用
use函数自动关闭输入流,避免出现资源泄漏问题。 - 增加了异常捕获逻辑,能处理用户取消选择、文件已被删除等异常场景。
内容的提问来源于stack exchange,提问作者Axel
相关产品推荐
相关产品推荐

