Spark Scala读取dat文件特殊字符避免乱码的解决方案求助
解决Spark Scala读取含特殊字符dat文件乱码问题
问题场景
使用Spark Scala读取包含短破折号、长破折号、英镑符号的dat文件时,特殊字符被替换为�,尝试过设置encoding为UTF-8、charset为ISO-8859-1,以及用regexp_replace处理均无效,需要可行的解决办法。
示例代码
val test = sparkSession.read.format("dat") .option("header", "false") .option("delimiter", "|") //.option("charset", "ISO-8859-1") //.option("encoding","UTF-8") .csv(csvPath) .filter(col("_c0").isNotNull) //.withColumn("_c1",regexp_replace(col("_c1"),"[^\\u0000-\\u007F]+","-")) .select(col("_c0").alias("id"), col("_c1").alias("test_string") ).dropDuplicates().cache
示例输出(IntelliJ控制台)
+---+-----------------------+ |id |test_string | +---+-----------------------+ |2 |Test Part2 � Test Part2| |1 |Test Part1 � Test Part1| +---+-----------------------+
可行解决方案
1. 确认文件真实编码
乱码核心原因通常是指定编码与文件实际编码不匹配。可以用Notepad++、chardet等工具检测文件真实编码(比如Windows-1252、GBK等,Windows系统生成的文件常使用这类编码)。
2. 修正读取逻辑并指定正确编码
Spark没有专门的dat格式读取器,代码中混用format("dat")和.csv(csvPath)是错误的,应统一使用csv格式读取,并设置正确编码:
import org.apache.spark.sql.functions.col val test = sparkSession.read.format("csv") .option("header", "false") .option("delimiter", "|") .option("encoding", "Windows-1252") // 替换为工具检测到的真实编码 .load(csvPath) .filter(col("_c0").isNotNull) .select(col("_c0").alias("id"), col("_c1").alias("test_string")) .dropDuplicates() .cache()
3. 排查控制台显示问题
IntelliJ控制台自身编码设置可能导致显示乱码,即使DataFrame中的数据是正确的:
- 打开IntelliJ设置:
File → Settings → Editor → File Encodings,将Global Encoding、Project Encoding、Default encoding for properties files均设为UTF-8,同时勾选Transparent native-to-ascii conversion。 - 也可以将数据写入文件验证:
打开输出文件检查特殊字符是否正常显示。test.write.format("csv").option("encoding", "UTF-8").save("output_path")
4. 自定义RDD读取方式(极端情况)
如果上述方法无效,可通过SparkContext直接读取文件并手动解析:
import org.apache.spark.sql.Row import org.apache.spark.sql.types.{StringType, StructField, StructType} // 提前定义Schema val schema = StructType(Seq( StructField("id", StringType), StructField("test_string", StringType) )) // 创建SparkSession时指定文件编码 val spark = SparkSession.builder() .appName("ReadDatFile") .config("spark.sql.files.encoding", "Windows-1252") // 替换为真实编码 .getOrCreate() // 读取文件并分割行(-1参数保留空值) val rawRDD = spark.sparkContext.textFile(csvPath).map(_.split("\\|", -1)) val df = spark.createDataFrame(rawRDD.map(arr => Row(arr(0), arr(1))), schema)
内容的提问来源于stack exchange,提问作者Prantik Banerjee
相关产品推荐
相关产品推荐

