如何将输出作为固定宽度的文件从Spark写入HDFS?

时间:2019-01-25 09:10:43

标签: python scala apache-spark hdfs

我必须从hdfs中读取一个csv文件,然后我需要应用将每一列都填充到固定宽度的逻辑,然后仅需要将其存储为hdfs作为固定宽度文件。没有任何其他形式的示例csv或镶木地板。

如果我将hdfs的输入读取为csv,如下例所示:

Name, age, phonenumber
A, 25,9900999999
B, 26,7654890234
C, 27,5643217897

然后我需要对固定宽度的每一列应用逻辑,例如第一列宽度应设置为15,第二列3,第三列应为10

在hdfs中输出应如下所示。

Name      age   phonenumber           
A         25    9900999999
B         26    7654890234
C         27    5643217897

然后,我需要将固定宽度数据作为固定宽度文件格式写入到hdfs中。

2 个答案:

答案 0 :(得分:0)

您的样本输出似乎带有分隔符,因为年龄和电话号码之间有空格。我猜想这是一个制表符分隔符,在这种情况下,您可以阅读csv并用spark.save.option("sep","\t").csv("filename")

保存回来

但是如果您所写的内容正确,则可以通过以下方式获得它:

import org.apache.spark.sql.functions.rpad
val df=spark.read.option("header","false").csv("...")
val out= df.select(rpad($"_c0",15," "),
                   rpad($"_c1",3," "),
                   rpad($"_c2",10," "))                   
out.map(_.mkString("")).write.text("filename")

请注意,我将标头设置为false,以便也将其填充

答案 1 :(得分:0)

如果已经使用了inferSchema,则需要将所有列都强制转换为字符串。 将长度映射到df.columns,以便可以动态处理。 检查一下:

scala> val df = Seq(("A", 25,9900999999L),("B", 26,7654890234L),("C", 27,5643217897L)).toDF("Name","age","phonenumber")
df: org.apache.spark.sql.DataFrame = [Name: string, age: int ... 1 more field]

scala> df.show(false)
+----+---+-----------+
|Name|age|phonenumber|
+----+---+-----------+
|A   |25 |9900999999 |
|B   |26 |7654890234 |
|C   |27 |5643217897 |
+----+---+-----------+


scala> val widths = Array(5,3,10)
widths: Array[Int] = Array(5, 3, 10)

scala> df.columns.zip(widths)
res235: Array[(String, Int)] = Array((Name,5), (age,3), (phonenumber,10))

scala> df.columns.zip(widths).foldLeft(df){ (acc,x) => acc.withColumn(x._1,rpad( trim(col(x._1).cast("string")),x._2," ")) }.show(false)
+-----+---+-----------+
|Name |age|phonenumber|
+-----+---+-----------+
|A    |25 |9900999999 |
|B    |26 |7654890234 |
|C    |27 |5643217897 |
+-----+---+-----------+

要验证填充。

scala> df.columns.zip(widths).foldLeft(df){ (acc,x) => acc.withColumn(x._1,rpad( trim(col(x._1).cast("string")),x._2,"-")) }.show(false)
+-----+---+-----------+
|Name |age|phonenumber|
+-----+---+-----------+
|A----|25-|9900999999 |
|B----|26-|7654890234 |
|C----|27-|5643217897 |
+-----+---+-----------+


scala>