Spark 1.6(Scala+Spark SQL)处理CSV编码字符与脏数据求助
在Spark 1.6(Scala+Spark SQL)中处理CSV乱码与过滤非字母数字行的方案
我来帮你梳理下Spark 1.6环境下的可行解决方案,分两个方向来处理你的问题:
一、先尝试从编码根源解决乱码问题
Spark 1.6本身没有内置CSV数据源,我们通常会用Databricks的spark-csv包来读取CSV文件——这个包其实是支持encoding配置项的,和Spark 2.x的用法类似!你可以试试在读取时指定正确的编码(注意要和原CSV文件的实际编码匹配),示例代码如下:
val df = sqlContext.read .format("com.databricks.spark.csv") .option("header", "true") // 如果你的CSV有表头就加这个 .option("encoding", "UTF-8") // 先试试UTF-8,不行的话换ISO-8859-1、GBK等常见编码 .load("/path/to/your/file.csv")
之前的乱码大概率是因为你指定的编码和原文件不匹配,比如原文件用的是Latin-1编码,你用UTF-8读取就会出现奇怪的字符,多试几种编码应该能解决问题。
二、如果编码问题无法解决,过滤/清理乱码行
你之前用WHERE COL LIKE "^[a-zA-Z0-9]*$"返回0条记录,是因为Spark 1.6的LIKE只支持简单通配符(%和_),不支持正则表达式的锚点(^和$)。要实现正则匹配过滤,得用Spark SQL的RLIKE函数,或者DataFrame API里的rlike方法。
1. 过滤仅含字母数字的行
如果只想保留地址列全是字母数字的行,可以这样写:
// DataFrame API方式 val filteredDf = df.filter(df("address").rlike("^[a-zA-Z0-9]*$")) // Spark SQL方式 df.registerTempTable("csv_table") val filteredDf = sqlContext.sql("SELECT * FROM csv_table WHERE address RLIKE '^[a-zA-Z0-9]*$'")
如果地址里允许空格、连字符这类合法字符,调整正则即可,比如^[a-zA-Z0-9\\s\\-]*$。
2. 过滤含不可打印乱码的行
如果乱码是不可见的控制字符,可以用\\p{Print}匹配所有可打印字符,过滤掉包含不可打印字符的行:
val filteredDf = df.filter(df("address").rlike("^[\\p{Print}]*$"))
3. 清理乱码字符(保留有用内容)
如果不想直接过滤行,而是想清理掉乱码字符,可以用regexp_replace函数替换掉非期望的字符:
import org.apache.spark.sql.functions.regexp_replace val cleanedDf = df.withColumn( "cleaned_address", regexp_replace(df("address"), "[^a-zA-Z0-9\\s\\-]", "") // 保留字母、数字、空格、连字符,其他替换为空 )
优先推荐先解决编码问题,这是最彻底的方案;如果编码确实无法匹配,再用过滤或清理的方式处理。
内容的提问来源于stack exchange,提问作者Sophie Dinka




