Spark:如何添加每个RDD的大小并写入新文件?

时间:2017-06-19 21:02:11

标签: scala apache-spark

我将每个事件保存在文本文件中,如下所示:

map{ case (_, record) => getEventFromRecord(record) }.map(m => m.toByteArray).saveAsTextFile(outputPath)

我还想保存我保存到文本文件的每个事件的总大小。 1)如何将每个记录的总大小保存到新文件? 2)我尝试使用累加器

val accum = sparkContext.accumulator(0, "My Accumulator")
map{ case (_, record) => getEventFromRecord(record) }.foreach(m => accum += (m.toByteArray.length)).saveAsTextFile(outputPath)

但是我收到以下错误:

            value saveAsTextFile is not a member of Unit

[error]     sparkContext.sequenceFile(inputDirectory, classOf[IntWritable], classOf[DataOutputValue]).map{ case (_, record) => getEventFromRecord(record) }.foreach(m => accum += (m.toByteArray.length)).saveAsTextFile(outputPath)
[error]                                                                                                                                                                                                            ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed

1 个答案:

答案 0 :(得分:1)

foreach动作返回单位作为结果,仅用于副作用。如果您想收集rdd的总和,请使用reduce操作

val totalSize = map{ case (_, record) => getEventFromRecord(record).toByteArray.length}.reduce{_ + _}

这将返回驱动程序上的求和结果。然后,您可以使用Hadoop Filesystem api创建一个新文件并写入它。

val fs = FileSystem.get(new Configuration())
val outputWriter = new PrintWriter(fs.create(outputPath))
outputWriter.println(totalSize)
outputWriter.flush()
outputWriter.close()

请注意,在生产中,您可能希望将该输出流包装到try / catch / finally块或类似内容中,以确保您的资源与您执行的任何文件IO一样正确关闭。