背景故事
android系统定制开发先看报错信息:
mismatched input ‘-’ expecting ‘:’
android系统定制开发报错的意思就是说,android系统定制开发在这个表里面,字段名中存在“-”,无法解析报错。
这个问题会发生在CDH
的spark
中。如果不是CDH
的spark
版本的程序,可以跳过此文章。
解决方案:
不要使用CDH
版本的spark
就好了。比如我这里出现报错的时候,使用的版本是2.4.0-cdh6.1.1
那么把这个版本修改为2.4.0
就好了。
过程分析
过程早就分析完了,下面写一篇结果:
环境版本
- spark-sql_2.11
2.4.0-cdh6.1.1 - spark-hive_2.11
2.4.0-cdh6.1.1
测试数据准备
SparkSession spark = SparkSession.builder().master("local").getOrCreate(); ArrayList<Row> rows = new ArrayList<>(); for (int i = 0; i < 4; i++) { rows.add(RowFactory.create(1, "张三", 18,"12345678")); } StructType schema = DataTypes.createStructType(new StructField[]{ DataTypes.createStructField("id", DataTypes.IntegerType, true), DataTypes.createStructField("name", DataTypes.StringType, true), DataTypes.createStructField("user-age", DataTypes.IntegerType, true), DataTypes.createStructField("number", DataTypes.StringType, true) }); spark.createDataFrame(rows,schema).write().orc("/Users/codes/testspark/src/orc"); spark.stop();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
测试数据样例(当然:
现在将spark
的版本切换为2.4.0-cdh6.1.1
开始读取这个数据/Users/codes/testspark/src/orc
果不其然,出现如下所示的报错信息,开始调试这个程序:
断点打到ParseDriver.scala
里面的withCommand
的方法
在Idea
的debug
栏里面看到:
这个user-age
字段被解析成了三个内容:user
、-
、age
.所以是这里出现了问题。
在非CDH
版本的spark
当中,这块儿变量会是什么样子呢?如下图所示:
在这个图里面,user-age
被成功解析了,并且套上了一对反引号。
那么,是什么东西造成了这样的不同呢?
核心原因:
原因是在CDH
的spark
中,有一个类org.apache.orc.TypeDescription
在解析数据schema
的过程中,不能正确识别字段中含有的特殊符号(cdh
版本的该类与开源版本相比缺失了一些解析字段名称的方法),也就不能给这些含有特殊符号的字段名称添加一对反引号。导致最后生成的。schema
信息过不去词法分析器步骤,所以报错。
具体的原因是在这表的结构信息转换成protobuf
格式的时候:
这块地方是cdh
版本的spark
调用的toString()
方法中的printToBuffer()
方法里面的详细内容:
这个是开源版本的:
这里多调用了一个printFieldName
的方法,我们开看看方法:
这里就是为了给字段名中添加反引号的地方了。
到这里,全部解释完毕了。
总结
原因找到了那么接下来的解决方案就好办了,可以对症下药。写到这里,如果各位大佬有什么更好的建议,请在下方留言: