由 cannot resolve ‘`a.stuID`‘ given input columns: [a.stuID, a.zhuanID, b.stuID, b.zhuanID]错误引发的思考

利用sparksql对两张表进行join,报错:

由 cannot resolve ‘`a.stuID`‘ given input columns: [a.stuID, a.zhuanID, b.stuID, b.zhuanID]错误引发的思考_第1张图片
检查表中字段:

发现两张表内都存在stuID。

折腾了好久也没弄好,后来不甘心,将数据转为txt格式,没想到同样的代码***跑通了***。

这可太amazing了,打开两个文档反复对比了一下。并没有什么不同,直到身边的大神让我查看一下文件的编码才发现端倪:

## 预览文件

head -n 1 xxx.txt | od -c

linux 下的od命令可以查看 这篇博客

结果显示:
由 cannot resolve ‘`a.stuID`‘ given input columns: [a.stuID, a.zhuanID, b.stuID, b.zhuanID]错误引发的思考_第2张图片发现csv文件的第一行第一列开头比txt多了三个字符,原因就在这:

再次打印 csv的列名,并查看每个的长度:

  var headerName = data.columns
    println("headName========",headerName.toList)
    for (x<- headerName){
      println("输出名称为:", x, " 输出长度为: ", x.length)
      println("逐次输出:~~~~~~~~~~~~~~~~~~")
      for(i<-0 until x.length){
        println("第", "个字符是::::", x(i).toByte)
      }
      println("@@@@@@@@@@@@@@结束@@@@@@@@@@@@")
    }

由 cannot resolve ‘`a.stuID`‘ given input columns: [a.stuID, a.zhuanID, b.stuID, b.zhuanID]错误引发的思考_第3张图片发现 csv文件读取的第一个列名stuID本来长度为5,结果打印结果为6。出现隐藏字符,对隐藏字符进行打印发现是空字符,并且byte为-1。
所以才导致多表join时,找不到 a.stuID。到此,终于弄清楚了问题所在。

查阅了相关资料发现,是叫做BOM(Byte Order Mark),直接顺序标记,出现在文本文件的头部,Unicode编码标准中用于标识文件是采用哪种格式的编码。没有BOM 则表示是默认的ASCII
BOM主要用途是记录哪种编码格式。

找到问题,解决起来就容易了很多。

随后查阅到spark2.x已经可以通过对应api 正常读取csv文件:

    val data = spark.read.format("csv")
              .option("sep", ",")
              .option("header", true)
              .option("nullValue", "")
              .csv(p.input_pt)
      

这样就不会有问题了。

附:

本文用到的csv文件和txt文件的下载地址 密码:wg35

拓展: spark将字符(Char)与字节编码(Byte)的相互转化

字符转字节:toByte
字节转字符:toChar

var s = "abc"
for (x <- 0 until s.length){
    println(s(x).toByte)
    println(s(x).toByte.toChar.toString)
}
println(100.toChar)

println(("-1".toByte.toChar)==(-1.toChar))

结果:
s: String = abc
97
a
98
b
99
c
d
true

你可能感兴趣的:(Scala,Spark,DateFrame)