Spark Scala读取Parquet后无法去除列名中空格问题求助
问题原因
- 你之前尝试的方案全部报错,是因为Spark默认在解析Parquet文件Schema时就会校验列名字符合法性,只要你读取数据后调用
columns/withColumnRenamed/toDF等任何需要访问Schema的方法,都会直接触发校验抛出异常,根本没执行到重命名的逻辑。
可行方案
方案1:开启兼容配置后重命名(适合列多、不想手动写Schema的场景)
创建SparkSession时添加允许列名含非法字符的兼容配置,之后就可以正常用批量重命名逻辑:
import org.apache.spark.sql.SparkSession val spark = SparkSession.builder() .appName("process-parquet-with-space-column") // 核心配置:允许列名包含非法特殊字符 .config("spark.sql.legacy.allowInvalidCharInColumnName", "true") .getOrCreate() // 读取文件 val df = spark.read.parquet("s3://tvsc-lumiq-edl/raw-v2/LMSDB/DESUSR/TBL_DES_SLA_MIS1") // 批量替换空格为下划线后重命名 val newCols = df.columns.map(c => c.replaceAll("\\s+", "_")) val cleanDf = df.toDF(newCols: _*) // 后续正常使用cleanDf即可
如果是Spark 2.x版本找不到上述配置,可以替换为:
.config("spark.sql.parser.escapedStringLiterals", "true")
方案2:手动指定Schema读取(适合列少、不想改全局配置的场景)
直接按照原文件的字段顺序和类型自定义Schema,读取时直接映射为无空格的列名,一步到位不需要额外重命名:
import org.apache.spark.sql.types._ // 按照原Parquet文件的字段顺序、类型、可空属性定义Schema,列名直接写替换后的无空格版本 val customSchema = StructType(Seq( StructField("dms_timestamp", StringType, nullable = true), StructField("BRANCH_NAME", StringType, nullable = true), StructField("BRANCH_CODE", StringType, nullable = true), StructField("DEALER_NAME", StringType, nullable = true), StructField("DEALER_CODE", StringType, nullable = true), StructField("DEALER_CATEGORY", StringType, nullable = true), StructField("PRODUCT", StringType, nullable = true), StructField("CREATION_DATE", StringType, nullable = true), StructField("CHANNEL_TYPE", StringType, nullable = true), StructField("DELAY_DAYS", StringType, nullable = true) )) // 读取时直接指定自定义Schema val df = spark.read.schema(customSchema).parquet("s3://tvsc-lumiq-edl/raw-v2/LMSDB/DESUSR/TBL_DES_SLA_MIS1")
内容的提问来源于stack exchange,提问作者whatsinthename
相关产品推荐
相关产品推荐

