spark中的saveAsTextFile方法

时间:2014-12-31 08:27:38

标签: scala apache-spark

在我的项目中,我有三个输入文件并将文件名设为args(0)到args(2),我也有一个输出文件名为args(3),在源代码中,我用

val sc = new SparkContext()
var log = sc.textFile(args(0))
for(i <- 1 until args.size - 1) log = log.union(sc.textFile(args(i)))

我对日志没有任何作用,但是使用

将其保存为文本文件
log.coalesce(1, true).saveAsTextFile(args(args.size - 1))

但它仍然保存为3个文件作为00000部分,部分00001,部分00002,那么有什么方法可以将三个输入文件保存到输出文件中?

2 个答案:

答案 0 :(得分:2)

拥有多个输出文件是Hadoop或Spark等多机群集的标准行为。输出文件的数量取决于reducer的数量。

如何在Hadoop中“解决”它: merge output files after reduce phase

如何在Spark中“解决”: how to make saveAsTextFile NOT split output into multiple file?

您也可以在这里获得一个很好的信息: http://apache-spark-user-list.1001560.n3.nabble.com/How-to-make-Spark-merge-the-output-file-td322.html

所以,你对coalesce(1,true)是正确的。但是,效率非常低。有趣的是(正如@climbage在他的评论中提到的),如果你在本地运行它,你的代码就可以了。

您可能尝试先读取文件然后保存输出。

...
val sc = new SparkContext()
var str = new String("")
for(i <- 0 until args.size - 1){
   val file = sc.textFile(args(i))       
   file.foreach(line => str+= line)
}
//and now you might save the content
str.coalesce(1, true).saveAsTextFile("out")

注意:此代码效率极低,仅适用于小文件!你需要提出一个更好的代码。我不会尝试减少文件数量,而是处理多个输出文件。

答案 1 :(得分:0)

如前所述,通过标准API,您的问题有些不可避免,因为您假设您正在处理大量数据。但是,如果我假设您的数据是可管理的,您可以尝试以下

import java.nio.file.{Paths, Files}    
import java.nio.charset.StandardCharsets

Files.write(Paths.get("./test_file"), data.collect.mkString("\n").getBytes(StandardCharsets.UTF_8))

我在这里做的是通过执行collect然后执行mkString将RDD转换为String。我建议不要在制作中这样做。它适用于本地数据分析(使用5gb本地数据)