Apache Spark:在reduce函数中构建文件/字符串

时间:2015-11-12 14:59:50

标签: scala mapreduce apache-spark

我正在使用一组相当大的txt文件,每个文件几个100MB。我想要做的是复制那些,我用函数MapFunc映射每一行。请看下面我的第一次尝试非常慢。我很确定问题在于reduce函数,它连接了这个巨大的字符串。

将行写入outputFile的顺序并不重要,但它们不能重叠。我已经看过Spark的saveAsTextFile但据我所知,我无法指定文件名,只能指定目录,这对我的用例没用。另外,添加页眉和页脚以及RDD元素之间的逗号怎么样?如果能够将此应用程序调整到最佳性能,我将不胜感激。

val conf = new SparkConf().setAppName("MyApp")
val sc = new SparkContext(conf)

val input = sc.textFile(file)
val lines = input.filter(s => filterFunc(s)).map(s => MapFunc(s))
val output = lines.reduce((a, b) => a + ',' + b)

val outputFile = new File(outFile)
val writer = new BufferedWriter(new FileWriter(outputFile))
val buf = new StringBuilder

buf ++= "header"
buf ++= output
buf ++= "footer"

writer.append(buf)
writer.flush()
writer.close()

编辑:我的文件是简单的csv文件。他们可以有评论(#)。此外,我需要确保只处理包含3列的文件,因为允许用户提交自己的文件进行处理。这是由FilterFunc完成的,说实话,它不会排除整个文件,只会排除与条件不匹配的行。一个简单的例子如下:

# File A
# generated mm/dd/yyyy
field11,field12,field13
field21,field22,field23
field31,field32,field33

输出填充如下所示:

$header
map(line1),
map(line2),
map(line3)
$footer

saveAsTextFile非常接近我正在寻找的东西。但正如已经说过的那样,我可以控制输出文件的文件名和位置。

1 个答案:

答案 0 :(得分:2)

您应该考虑直接写入文件,而不是使用临时缓冲区buf

val writer = new PrintWriter(new File(outFile))
writer.print("header")
writer.print(output)
writer.print("footer")
writer.flush()
writer.close()

您可以避免连接,也可以消耗buf的内存。