Spark可以将rdd保存到rdd.saveAsObjectFile("file")
的文件中。
我需要在Spark之外读取这个文件。根据{{3}},使用默认的spark序列化程序,此文件只是使用标准Java序列化序列化的一系列对象。但是,我猜该文件有一个标题和对象之间的分隔符。我需要读取此文件,并使用doc反序列化每个Java / Scala对象(因为我没有类定义)。
在哪里可以找到有关rdd.saveAsObjectFile("file")
生成的文件格式的文档(使用标准序列化程序,而不是Kryo序列化程序)?
更新 基于VladoDemcak的工作示例回答:
import org.apache.hadoop.io._
import org.apache.hadoop.conf._
import org.apache.hadoop.fs._
import org.apache.hadoop.io._
def deserialize(data: Array[Byte]) =
new ObjectInputStream(new ByteArrayInputStream(data)).readObject()
val path = new Path("/tmp/part-00000")
val config = new Configuration()
val reader = new SequenceFile.Reader(FileSystem.get(new Configuration()), path, config)
val key = NullWritable.get
val value = new BytesWritable
while (reader.next(key, value)) {
println("key: {} and value: {}.", key, value.getBytes)
println(deserialize(value.getBytes()))
}
reader.close()
答案 0 :(得分:1)
这是一个非常有趣的问题,所以我将尝试解释我对这些工作人员的了解。您可以查看saveAsObjectFile
以及我看到的有关详细信息is API javadoc
/**
* Save this RDD as a SequenceFile of serialized objects.
*/
def saveAsObjectFile(path: String): Unit = withScope {
this.mapPartitions(iter => iter.grouped(10).map(_.toArray))
.map(x => (NullWritable.get(), new BytesWritable(Utils.serialize(x))))
.saveAsSequenceFile(path)
}
据我所知saveAsObjectFile
生成SequenceFile
。基于sequenceFile的文档,它的标题包含version
,classname
,metadata
...
有3种不同的SequenceFile格式:
未压缩的键/值记录。记录压缩的键/值记录 - 这里只压缩'值'。阻止压缩的键/值记录 - 键和值分别在'块'中收集并压缩。 “块”的大小是可配置的。
所有上述格式共享一个公共标题(由...使用) SequenceFile.Reader返回相应的键/值对。
对于读取序列文件,我们可以使用hadoop SequenceFile.Reader实现。
Path path = new Path("/hdfs/file/path/seqfile");
SequenceFile.Reader reader = new SequenceFile.Reader(FileSystem.get(new Configuration()), path, config);
WritableComparable key = (WritableComparable) reader.getKeyClass().newInstance();
Writable value = (Writable) reader.getValueClass().newInstance();
while (reader.next(key, value)){
logger.info("key: {} and value: {}.", key, value.getBytes());
// (MyObject) deserialize(value.getBytes());
}
reader.close();
我没有对此进行测试,但根据您在问题中注意到的doc链接:
默认情况下,Spark使用Java的ObjectOutputStream序列化对象 框架
所以在循环中你可以得到值的字节,并用ObjectInputStream
public static Object deserialize(byte[] data){
return new ObjectInputStream(new ByteArrayInputStream(data)).readObject();
}
在你的情况下你需要在反序列化方法中使用你的库(jdeserialize) - 我猜run(InputStream is, boolean shouldConnect)
等。