在Spark中保存文本文件之前添加标题

时间:2014-10-02 08:57:06

标签: apache-spark

我有一些处理csv文件的spark代码。它对它做了一些改造。我现在想将此RDD保存为csv文件并添加标头。此RDD的每一行都已正确格式化。

我不知道该怎么做。我想用标题字符串和我的RDD进行联合,但标题字符串不是RDD所以它不起作用。

5 个答案:

答案 0 :(得分:10)

您可以从标题行中创建一个RDD,然后union它,是的:

val rdd: RDD[String] = ...
val header: RDD[String] = sc.parallelize(Array("my,header,row"))
header.union(rdd).saveAsTextFile(...)

然后你最终得到了一堆你合并的part-xxxxx个文件。

问题在于,我不认为您确保标题将成为第一个分区,因此最终会出现在part-00000和文件顶部。在实践中,我非常肯定它会。

更可靠的是使用像hdfs这样的Hadoop命令来合并part-xxxxx文件,并且作为命令的一部分,只需从文件中输入标题行。

答案 1 :(得分:0)

在没有Union的情况下编写它的一些帮助(在合并时提供标题)

val fileHeader ="This is header"
val fileHeaderStream: InputStream = new  ByteArrayInputStream(fileHeader.getBytes(StandardCharsets.UTF_8));
val output = IOUtils.copyBytes(fileHeaderStream,out,conf,false)

现在循环遍历文件部分,使用

编写完整的文件
val in: DataInputStream = ...<data input stream from file >
 IOUtils.copyBytes(in, output, conf, false)

这确保了即使你使用coalasec / repartition进行高效写作,标题总是作为第一行出现

答案 2 :(得分:0)

def addHeaderToRdd(sparkCtx: SparkContext, lines: RDD[String], header: String): RDD[String] = {

    val headerRDD = sparkCtx.parallelize(List((-1L, header)))     // We index the header with -1, so that the sort will put it on top.

    val pairRDD = lines.zipWithIndex()

    val pairRDD2 = pairRDD.map(t => (t._2, t._1))

    val allRDD = pairRDD2.union(headerRDD)

    val allSortedRDD = allRDD.sortByKey()

    return allSortedRDD.values
}

答案 3 :(得分:0)

使用Spark SQL

进行轻微差异处理
  

来自问题:我现在想将此RDD保存为CSV文件并添加标题。此RDD的每一行都已正确格式化。

使用Spark 2.x,您可以选择convert RDD to DataFrame

val rdd = .... //Assume rdd properly formatted with case class or tuple
val df = spark.createDataFrame(rdd).toDF("col1", "col2", ... "coln")

df.write
  .format("csv")
  .option("header", "true")  //adds header to file
  .save("hdfs://location/to/save/csv")

现在我们甚至可以使用Spark SQL DataFrame来加载,转换和保存CSV文件

答案 4 :(得分:0)

spark.sparkContext.parallelize(Seq(SqlHelper.getARow(temRet.columns, 
temRet.columns.length))).union(temRet.rdd).map(x => 
x.mkString("\x01")).coalesce(1, true).saveAsTextFile(retPath)


object SqlHelper {
//create one row
def getARow(x: Array[String], size: Int): Row = {
var columnArray = new Array[String](size)
for (i <- 0 to (size - 1)) {
  columnArray(i) = x(i).toString()
}
Row.fromSeq(columnArray)
}
}