如何使用ContentResolver设置所创建文件的编码格式?
修复CSV文件编码乱码方案
问题原因
你当前的代码默认使用UTF-8编码生成字节流,而微软Office读取CSV文件时默认使用当前系统区域的编码(俄文地区为Windows-1251)解码,没有BOM标识的UTF-8文件会被错误解码,因此西里尔字符显示乱码。
另外你的代码中存在两处可优化点:
openOutputStream可能返回null,需要添加空安全调用use函数会在执行完成后自动关闭流,不需要额外调用out.close()
方案1:指定Windows-1251编码
如果需要适配俄文区域的Office默认编码,直接指定编码转换即可:
private val getContent = registerForActivityResult(ActivityResultContracts.CreateDocument("text/csv")) { uri -> uri?.let { writeToFile(requireActivity(), it) } } fun writeToFile(context: Context, source: Uri) = viewModelScope.launch(Dispatchers.IO) { val contentResolver = context.contentResolver contentResolver.openOutputStream(source)?.use { out -> // 直接指定Windows-1251编码转换字节 out.write("id,Цвет,Размер\n".toByteArray(Charsets.Windows_1251)) } }
方案2:使用带BOM的UTF-8编码(多区域兼容)
如果需要文件在不同语言区域的设备上都能正常显示,推荐写入UTF-8 BOM头,Office识别到BOM后会自动使用UTF-8解码:
fun writeToFile(context: Context, source: Uri) = viewModelScope.launch(Dispatchers.IO) { val contentResolver = context.contentResolver contentResolver.openOutputStream(source)?.use { out -> // 写入UTF-8 BOM头 out.write(byteArrayOf(0xEF.toByte(), 0xBB.toByte(), 0xBF.toByte())) // 写入UTF-8编码的内容 out.write("id,Цвет,Размер\n".toByteArray(Charsets.UTF_8)) } }
其他编码设置方式
如果需要设置其他编码,只需要替换toByteArray()方法中的编码参数即可,例如:
Charsets.UTF_16对应Unicode双字节编码- 也可以直接传入编码名称字符串,例如
toByteArray(Charset.forName("GBK"))
内容的提问来源于stack exchange,提问作者SoulReaver313
相关产品推荐
相关产品推荐

