AWS Glue中Spark写入CSV时ISO-8859-1编码不生效问题
AWS Glue中Spark CSV输出ISO-8859-1/cp1252编码不生效的原因及解决办法
核心原因
- Spark的CSV写入器针对单字节编码(如ISO-8859-1、cp1252)有隐性优化:当数据所有字符都属于ASCII范围(0-127)时,Spark会默认输出UTF-8编码——因为UTF-8对ASCII字符的编码与这些单字节编码完全兼容,这种情况下指定的编码参数会被忽略。
- AWS Glue依赖的Hadoop TextOutputFormat在处理部分单字节编码时,若数据无超出ASCII的字符,会自动 fallback 到UTF-8,导致编码配置不生效。而UTF-16是双字节编码,不存在这种兼容优化,所以设置后能正常生效。
解决办法
1. 强制触发编码转换
通过临时添加一个属于ISO-8859-1/cp1252范围的非ASCII字符,让Spark触发指定编码的写入逻辑,之后可再移除该字符:
from pyspark.sql.functions import lit # 临时添加包含非ASCII字符的列(比如版权符号©,对应ISO-8859-1的169) df_with_dummy = df.withColumn("dummy_col", lit(chr(169))) # 写入CSV df_with_dummy.write.mode("overwrite")\ .partitionBy("partition_date")\ .option("encoding", "ISO-8859-1")\ .option("header", "true")\ .csv(tmp_s3_path) # 可选:读取生成的文件并移除临时列,得到最终文件 final_df = spark.read.option("encoding", "ISO-8859-1")\ .option("header", "true")\ .csv(tmp_s3_path) final_df.drop("dummy_col").write.mode("overwrite")\ .partitionBy("partition_date")\ .option("encoding", "ISO-8859-1")\ .option("header", "true")\ .csv(final_s3_path)
2. 通过Hadoop配置强制编码
直接设置Hadoop的输出编码属性,绕过Spark的兼容优化:
# 获取当前Spark会话的Hadoop配置 spark._jsc.hadoopConfiguration().set("io.file.encoding", "ISO-8859-1") spark._jsc.hadoopConfiguration().set("textoutputformat.record.delimiter", "\n") # 执行CSV写入 df.write.mode("overwrite")\ .partitionBy("partition_date")\ .option("encoding", "ISO-8859-1")\ .option("header", "true")\ .csv(tmp_s3_path)
3. 正确验证编码
避免依赖系统默认工具的编码检测(如Windows记事本),用专业工具或代码验证:
import chardet # 本地文件验证示例(若文件在S3可先下载到本地) with open("target_csv_file.csv", "rb") as f: detection_result = chardet.detect(f.read()) print(f"检测到的编码:{detection_result['encoding']}")
内容的提问来源于stack exchange,提问作者Fredrik
相关产品推荐
相关产品推荐

