Error: Unable to find encoder for type stored in a Dataset. Primitive types (Int, String, etc) and Product types (case classes) are supported by importing spark.implicits._ Support for serializing other types will be added in future releases.
准备打包运行,在打包的时候总是出现上面的错误
比如现在的数据是下面这样的,多了一列time
5426 程凡 G56 2013-12-24 17:26:23 龙岩 苗栗
4413 相承 TV7 2014-04-09 20:44:25 北票 开原
如果在用下面的代码又出现同样的错误
implicit val matchError = org.apache.spark.sql.Encoders.tuple( Encoders.STRING, Encoders.STRING, Encoders.STRING, Encoders.STRING, Encoders.STRING)
因为在Encoders中最多支持5个元素的tuple,我们需要将DataSet转成处理成Row类型的,最后转成RDD用数据和表头创建一个DataFrame
错误:无法找到存储在数据集中的类型的编码器。原始类型(Int,String等)和产品类型(case类)由导入spark.implicits支持。支持对其他类型的序列化,将在以后的版本中添加。
问题解决如下:
在开发过程中,我想将已经保存在HDFS上的文本文件保存成CSV格式的文件。
以前文件格式如下(这里使用自己造的假数据)每一列所对应的是 id,name,no,sp,ep
3303 龙顺 JD8 赤壁 湛江
5426 程凡 G58 龙岩 苗栗
我想处理成下面的格式,因为下面的格式是CSV默认格式
id,name,no,sp,ep
1309,项敬,BKZ,韶关,湖北
3507,宁风晨,KY7,河源,资阳
处理代码如下
def main(args: Array[String]) { val sparkSession = SparkSession.builder().appName("Spark shell").getOrCreate() //文件路径 val path = "hdfs://master:9000/TestData/aviation9" //保存路径 val savePath = "hdfs://master:9000/TestData/aviation10/" val file = sparkSession.read.textFile(path) //处理数据,拆分 val rd = file.map(line => { val arr = line.split("\t") (arr(0), arr(1), arr(2), arr(3), arr(4)) }) //给DataFrame添加表头, val res = rd.toDF("id", "name", "no", "sp", "ep") //保存有表的文件 res.repartition(1).write.mode(SaveMode.Append).format("csv").option("header", true).save(savePath) }
准备打包运行,在打包的时候总是出现上面的错误
无法找到存储在数据集中的类型的编码器。
原始类型(Int,String等)和产品类型(case类)由导入spark.implicits支持。
支持对其他类型的序列化,将在以后的版本中添加。
所以需要我们自己在Dataset中添加元组这样的编码
解决办法:处理数据之间添加下面一行代码
implicit val matchError = org.apache.spark.sql.Encoders.tuple( Encoders.STRING, Encoders.STRING, Encoders.STRING, Encoders.STRING, Encoders.STRING)
最后的全部代码是
def main(args: Array[String]) { val sparkSession = SparkSession.builder().appName("Spark shell").getOrCreate() //文件路径 val path = "hdfs://master:9000/TestData/aviation9" //保存路径 val savePath = "hdfs://master:9000/TestData/aviation10/" val file = sparkSession.read.textFile(path) implicit val matchError = org.apache.spark.sql.Encoders.tuple( Encoders.STRING, Encoders.STRING, Encoders.STRING, Encoders.STRING, Encoders.STRING) //处理数据,拆分 val rd = file.map(line => { val arr = line.split("\t") (arr(0), arr(1), arr(2), arr(3), arr(4)) }) //给DataFrame添加表头, val res = rd.toDF("id", "name", "no", "sp", "ep") //保存有表的文件 res.repartition(1).write.mode(SaveMode.Append).format("csv").option("header", true).save(savePath) }
比如现在的数据是下面这样的,多了一列time
5426 程凡 G56 2013-12-24 17:26:23 龙岩 苗栗
4413 相承 TV7 2014-04-09 20:44:25 北票 开原
如果在用下面的代码又出现同样的错误
implicit val matchError = org.apache.spark.sql.Encoders.tuple( Encoders.STRING, Encoders.STRING, Encoders.STRING, Encoders.STRING, Encoders.STRING)
因为在Encoders中最多支持5个元素的tuple,我们需要将DataSet转成处理成Row类型的,最后转成RDD用数据和表头创建一个DataFrame
def main(args: Array[String]) { val sparkSession = SparkSession.builder().appName("Spark shell").getOrCreate() val fields = "id,name,no,time,sp,ep" val path = "hdfs://master:9000/TestData/aviation9" val savePath = "hdfs://master:9000/TestData/aviation10/" val file: Dataset[String] = sparkSession.read.textFile(path) implicit val matchError = org.apache.spark.sql.Encoders.kryo[Row] //处理成Row val ds = file.map(x => { val arr = x.split("\t") Row.fromSeq(arr.toSeq) }) //创建表头 val field_array = fields.split(",") val schema = StructType(field_array.map(fieldName => StructField(fieldName, StringType, true))) //创建DataFrame val df = sparkSession.createDataFrame(ds.rdd, schema) df.repartition(1).write.mode(SaveMode.Append).format("csv").option("header", true).save(savePath) }