【发布时间】:2019-01-20 23:14:25
【问题描述】:
我的下一个问题并不新鲜,但我想了解如何一步一步完成。
在 Spark 应用程序中,我创建了 DataFrame。让我们称之为df。 Spark 版本:2.4.0
val df: DataFrame = Seq(
("Alex", "2018-01-01 00:00:00", "2018-02-01 00:00:00", "OUT"),
("Bob", "2018-02-01 00:00:00", "2018-02-05 00:00:00", "IN"),
("Mark", "2018-02-01 00:00:00", "2018-03-01 00:00:00", "IN"),
("Mark", "2018-05-01 00:00:00", "2018-08-01 00:00:00", "OUT"),
("Meggy", "2018-02-01 00:00:00", "2018-02-01 00:00:00", "OUT")
).toDF("NAME", "START_DATE", "END_DATE", "STATUS")
如何从这个DataFrame创建.csv文件并将csv文件放到服务器的特定文件夹中?
例如,这段代码是否正确?我注意到有些人使用coalesce 或repartition 来完成这项任务。但我不明白在我的情况下哪一个会更好。
union.write
.format("com.databricks.spark.csv")
.option("header", "true")
.save("/home/reports/")
当我尝试使用下一个代码时,它会引发 ERROR:
org.apache.hadoop.security.AccessControlException: Permission denied: user=root, access=WRITE, inode="/home/reports/_temporary/0":hdfs:hdfs:drwxr-xr-x
我以root 用户身份运行 Spark 应用程序。 reports 由root 用户使用下一条命令创建的文件夹:
mkdir -m 777 reports
好像只有hdfs用户可以写文件。
【问题讨论】:
-
在 Spark 2.* 中,您可以使用语法
dataFrame.option("header", "true").csv("/home/reports/")。但是你不应该混淆本地文件系统和 HDFS。您指定的路径是 HDFS 上的路径。您的用户无权写入该位置。如果您想写入服务器上的本地目录,您应该首先使用val dataToSave = dataFrame.collect()收集数据。如果这样做,与 DataFrame 相关的所有数据都将转到 Spark 主节点。因此,请确保您有足够的内存。之后,您将能够使用标准 Scala/Java IO API 保存数据。 -
不,我不是这个意思。您可以使用
dataToSave.write.csv(path)将数据保存到 HDFS 或 S3。如果要将 DataFrame 保存到服务器上的某个位置。你应该做val dataToSave = dataFrame.collect()。之后,数据将包含在 Spark 主节点的内存中。然后你可以使用PrintWriter或FileWriter来保存数据。 -
如果你决定在 DataFrame 上使用
collect方法,你会得到Array[Row]。之后你可以做val linesToSave: Array[String] = dataToSave.map(_.toSeq.mkString(";"))。此外,您可以查看au.com.bytecode.opencsv.CSVWriter以从Array[Row]创建 csv 文件。 -
其实,最简单的方法是使用第一条评论页面中描述的方法。您可以将文件写入 HDFS 上的某个临时位置(例如:/tmp),并在作业完成后将其复制/移动到本地目录。
标签: scala apache-spark