如何从ActivityResultContracts返回的Content URI获取并解析CSV文件
从Content URI解析CSV的实现方案
由于Android 10+分区存储限制,不要尝试将Content URI转换为本地绝对路径,直接通过
ContentResolver打开输入流读取内容是兼容所有版本的正确方案。
实现步骤
- 通过ContentResolver打开选中CSV的输入流,利用Kotlin的
use扩展自动管理流关闭,避免内存泄漏 - 读取流内容,根据CSV的复杂程度选择自定义逐行解析或者第三方CSV解析库处理
代码示例
基础无依赖解析(适用于无转义的简单CSV)
直接在你现有回调的uri?.let块中填入以下逻辑:
uri?.let { csvUri -> contentResolver.openInputStream(csvUri)?.use { inputStream -> // 可根据CSV实际编码调整,Windows导出的CSV常为GBK编码 val reader = InputStreamReader(inputStream, Charsets.UTF_8) val bufferedReader = BufferedReader(reader) val csvData = mutableListOf<List<String>>() bufferedReader.forEachLine { line -> // 简单CSV直接按逗号拆分,带引号/逗号的复杂场景不适用 val rowCells = line.split(",") csvData.add(rowCells) } // csvData即为解析完成的二维数据,第一行通常为表头 } }
复杂CSV场景的处理说明
如果你的CSV包含带逗号的引号包裹单元格、单元格内换行这类复杂格式,直接按逗号拆分会出现解析错误,可以引入OpenCSV、Apache Commons CSV这类成熟解析库,直接将输入流传入解析器即可自动处理转义逻辑,示例代码逻辑:
// 在openInputStream返回的流的use块中 inputStream.bufferedReader().use { reader -> // 对应CSV解析库的读对象初始化 val csvReader = CSVReader(reader) val allRows = csvReader.readAll() // 自动处理各类转义规则,直接拿到全量行数据 }
注意事项
- 大文件处理:如果CSV体积较大,不要一次性把所有行加载到内存,用上述逐行读取的逻辑边读边处理业务,避免OOM
- 编码适配:如果解析出现中文乱码,优先尝试把字符集换成
Charset.forName("GBK"),适配Windows导出的CSV默认编码 - 权限兼容:通过OpenDocument SAF返回的URI自带临时读权限,无需额外申请存储权限,完全适配分区存储规则
内容的提问来源于stack exchange,提问作者Noyal Jose
相关产品推荐
相关产品推荐

