Spark写CSV时指定encoding不生效,如何输出指定编码的CSV文件?
Spark DataFrame写入CSV指定编码不生效的解决方法
根因分析
- Spark 2.3及更早版本存在已知bug:CSV写入的
encoding参数仅读取生效,写入时会被强制固定为UTF-8,因此修改参数不生效。 - 部分Windows系统自带的文本编辑器存在编码识别误差,可能误将GBK文件识别为UTF-8,导致误判参数失效。
解决方法
方案1:升级Spark版本(最简便)
升级到Spark 2.4及以上版本,CSV写入的encoding参数已修复,你原来的写法可以直接生效:
df.repartition(1) .write .option("header", true) .option("encoding", "GBK") .csv("F:\\project\\test1")
如果还是不生效,可以尝试将编码值替换为GBK的超集GB18030,兼容性更强:
.option("encoding", "GB18030")
方案2:低版本Spark手动指定编码写出(无需升级)
如果暂时无法升级Spark版本,可以转为RDD手动指定GBK编码写出:
import org.apache.hadoop.io.Text import org.apache.hadoop.mapred.TextOutputFormat // 拼接表头和数据行 val header = df.columns.mkString(",") val dataRdd = df.rdd.map(row => row.toSeq.map(f => if(f == null) "" else f.toString).mkString(",")) val allRdd = df.sparkSession.sparkContext.parallelize(Seq(header)) ++ dataRdd // 配置写出编码为GBK val sc = df.sparkSession.sparkContext sc.hadoopConfiguration.set("textoutputformat.encoding", "GBK") sc.hadoopConfiguration.set("mapreduce.output.textoutputformat.separator", "") allRdd.map(line => (null, new Text(line.getBytes("GBK")))) .saveAsHadoopFile[TextOutputFormat[Void, Text]]("F:\\project\\test1")
验证注意事项
不要使用Windows自带记事本检测文件编码,建议使用Notepad++等专业编辑器的「编码」菜单查看,或使用编码检测工具验证,避免识别误差。
内容的提问来源于stack exchange,提问作者kevinX
相关产品推荐
相关产品推荐

