Scala:如何从RDD获取PortableDataStream实例的内容
当我想从二进制文件中提取数据时,我使用Scala:如何从RDD获取PortableDataStream实例的内容,scala,apache-spark,rdd,Scala,Apache Spark,Rdd,当我想从二进制文件中提取数据时,我使用 val dataRDD=sc.binaryRecord(“Path”)我得到的结果是org.apache.spark.rdd.rdd[(String,org.apache.spark.input.PortableDataStream)] 我想以PortableDataStream 为此,我尝试了:val data=dataRDD.map(x=>x.\u 2.open()).collect() 但我得到了以下错误: java.io.NotSerializab
val dataRDD=sc.binaryRecord(“Path”)
我得到的结果是org.apache.spark.rdd.rdd[(String,org.apache.spark.input.PortableDataStream)]
我想以PortableDataStream
为此,我尝试了:val data=dataRDD.map(x=>x.\u 2.open()).collect()
但我得到了以下错误:
java.io.NotSerializableException:org.apache.hadoop.hdfs.client.HdfsDataInputStream
如果你有一个想法,我可以如何解决我的问题,请帮助
非常感谢。实际上,
PortableDataStream
是可序列化的。这就是它的意义所在。然而,open()
返回一个简单的DataInputStream
(HdfsDataInputStream
,因为您的文件在HDFS上),它是不可序列化的,因此会出现错误
事实上,当您打开PortableDataStream时,您只需要立即读取数据。在scala中,您可以使用scala.io.Source.fromInputStream
:
val数据:RDD[Array[String]]=sc
.binaryFiles(“路径/../”)
.map{case(文件名,pds)=>{
scala.io.Source.fromInputStream(pds.open())
.getLines().toArray
}}
此代码假定数据是文本的。如果不是,您可以调整它以读取任何类型的二进制数据。下面是一个创建字节序列的示例,您可以按照自己的方式处理该序列
val rdd : RDD[Seq[Byte]] = sc.binaryFiles("...")
.map{ case (file, pds) => {
val dis = pds.open()
val bytes = Array.ofDim[Byte](1024)
val all = scala.collection.mutable.ArrayBuffer[Byte]()
while( dis.read(bytes) != -1) {
all ++= bytes
}
all.toSeq
}}
有关更多可能性,请参阅。例如,它拥有readLong
、readDouble
(等等)方法
val bytes=bf.map{case(file,pds)=>{
val dis=pds.open()
val len=dis.available();
val buf=数组。ofDim[字节](len)
pds.open().readFully(buf)
缓冲器
}}
bytes:org.apache.spark.rdd.rdd[Array[Byte]]=MapPartitionsRDD[21]位于map at:26
scala>bytes.take(1)(0).size
res15:Int=5879609//这恰好是我的第一个二进制文件的大小
感谢您的回复。我已经尝试了您的解决方案,缺少一个“}”,并且我应该将
.toSeq()
编辑到.toSeq
否则它会给我错误:没有足够的参数用于trait SeqLike中的方法apply:(idx:Int)字符串。尽管解决方案给出了错误调度器.TaskSetManager:阶段1.0中的任务0失败1次;正在中止作业
对不起,我没有测试所有代码。我修正了我的答案。它实际上不适用于toSeq
,可能是因为它只是基于inputStream封装了迭代器toArray
相反,实际提取数据以将其放入数组中。我在答案中修改了它。感谢您的反馈;)感谢@Oli的回复。问题仍然存在java.nio.charset.MalformedInputException:Input length=1
OK,这是不同的。你在读什么样的数据?这只是字符串的一个示例。如果您读取二进制数据,它将无法工作,您必须调整代码。。。
val bf = sc.binaryFiles("...")
val bytes = bf.map{ case(file, pds) => {
val dis = pds.open()
val len = dis.available();
val buf = Array.ofDim[Byte](len)
pds.open().readFully(buf)
buf
}}
bytes: org.apache.spark.rdd.RDD[Array[Byte]] = MapPartitionsRDD[21] at map at <console>:26
scala> bytes.take(1)(0).size
res15: Int = 5879609 // this happened to be the size of my first binary file