Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Azure Databricks将文件写入Azure DataLake Gen 2_Scala_Azure_Azure Data Lake_Databricks_Azure Databricks - Fatal编程技术网

Scala Azure Databricks将文件写入Azure DataLake Gen 2

Scala Azure Databricks将文件写入Azure DataLake Gen 2,scala,azure,azure-data-lake,databricks,azure-databricks,Scala,Azure,Azure Data Lake,Databricks,Azure Databricks,我有一个Azure Data Lake gen1和一个Azure Data Lake gen2(Blob存储和分层存储),我正在尝试创建一个DataRicks笔记本(Scala),它可以读取2个文件,并将一个新文件写回Data Lake。在Gen1和Gen2中,我遇到了相同的问题,即我指定的输出csv的文件名被保存为一个目录,并且在该目录中,它正在写入4个文件“提交、启动、成功和部分-00000-tid”- 就我个人而言,我不明白为什么它会这样做,而不是将csv保存到该位置。 下面是我编写的代

我有一个Azure Data Lake gen1和一个Azure Data Lake gen2(Blob存储和分层存储),我正在尝试创建一个DataRicks笔记本(Scala),它可以读取2个文件,并将一个新文件写回Data Lake。在Gen1和Gen2中,我遇到了相同的问题,即我指定的输出csv的文件名被保存为一个目录,并且在该目录中,它正在写入4个文件“提交、启动、成功和部分-00000-tid”-

就我个人而言,我不明白为什么它会这样做,而不是将csv保存到该位置。 下面是我编写的代码示例。如果我在df_join数据帧上执行.show(),它将输出正确的结果。但是.write无法正常工作

val df_names = spark.read.option("header", "true").csv("/mnt/datalake/raw/names.csv")
val df_addresses = spark.read.option("header", "true").csv("/mnt/datalake/raw/addresses.csv")

val df_join = df_names.join(df_addresses, df_names.col("pk") === df_addresses.col("namepk"))


df_join.write
.format("com.databricks.spark.csv")
.option("header", "true")
.mode("overwrite")
.save("/mnt/datalake/reports/testoutput.csv")

之所以要创建一个包含多个文件的目录,是因为每个分区都是单独保存并写入数据湖的。要保存单个输出文件,需要重新分区数据帧

让我们使用DataFrameAPI

confKey = "fs.azure.account.key.srcAcctName.blob.core.windows.net"
secretKey = "==" #your secret key
spark.conf.set(confKey,secretKey)
blobUrl = 'wasbs://MyContainerName@srcAcctName.blob.core.windows.net'
合并您的数据帧

df_join.coalesce(1)
.write
.format("com.databricks.spark.csv")
.option("header", "true")
.mode("overwrite")
.save("blobUrl" + "/reports/")
更改文件名

files = dbutils.fs.ls(blobUrl + '/reports/')
output_file = [x for x in files if x.name.startswith("part-")]
dbutils.fs.mv(output_file[0].path, "%s/reports/testoutput.csv" % (blobUrl))

之所以要创建一个包含多个文件的目录,是因为每个分区都是单独保存并写入数据湖的。要保存单个输出文件,需要重新分区数据帧

让我们使用DataFrameAPI

confKey = "fs.azure.account.key.srcAcctName.blob.core.windows.net"
secretKey = "==" #your secret key
spark.conf.set(confKey,secretKey)
blobUrl = 'wasbs://MyContainerName@srcAcctName.blob.core.windows.net'
合并您的数据帧

df_join.coalesce(1)
.write
.format("com.databricks.spark.csv")
.option("header", "true")
.mode("overwrite")
.save("blobUrl" + "/reports/")
更改文件名

files = dbutils.fs.ls(blobUrl + '/reports/')
output_file = [x for x in files if x.name.startswith("part-")]
dbutils.fs.mv(output_file[0].path, "%s/reports/testoutput.csv" % (blobUrl))

如果我正确理解您的需求,您只需要将Spark数据帧数据写入一个名为
testoutput.csv
的csv文件到Azure data Lake中,而不是一个名为
testoutput.csv
的目录和一些分区文件

因此,您无法通过使用这些Spark函数(如
DataFrameWriter.save
)直接实现它,因为实际上DataFrameWriter基于Azure data Lake将数据写入HDFS。HDFS将数据持久化为名为您的目录和一些分区文件。请参阅一些有关HDFS的文档,以了解它


然后,根据我的经验,您可以尝试在Scala程序中使用Azure Data Lake SDK for Jave直接将数据帧作为单个文件写入Azure Data Lake。您可以参考一些示例。

如果我正确理解您的需要,您只需将Spark DataFrame数据写入名为
testout的单个csv文件将.csv
放入Azure Data Lake,而不是名为
testoutput.csv的目录,其中包含一些分区文件

因此,您无法通过使用这些Spark函数(如
DataFrameWriter.save
)直接实现它,因为实际上DataFrameWriter基于Azure data Lake将数据写入HDFS。HDFS将数据持久化为名为您的目录和一些分区文件。请参阅一些有关HDFS的文档,以了解它


然后,根据我的经验,您可以尝试在Scala程序中使用Azure Data Lake SDK for Jave将数据从DataFrame直接写入Azure Data Lake作为单个文件。您可以参考一些示例。

谢谢您的评论。这会将一个csv文件保存到Data Lake中,但不会以指定的名称保存。它仍然会忽略s是文件名,只将文件“part-00000-tid…”写入目录名。做了进一步的研究后,我认为不可能用特定的文件名保存到数据湖。这对我来说仍然很奇怪。如果你要走这条路,你应该使用
.coalesce(1)
而不是
.repartition(1)
减少节点之间的数据移动。重新分区将对所有节点的数据执行完全洗牌,然后再将其减少为单个分区。@DavidP您是100%正确的。我将相应地更改答案。感谢您的评论。这会将一个csv文件保存到数据池中,但不会以指定的名称保存。它仍然忽略重新设置文件名,并仅使用“part-00000-tid…”文件写入目录名。在做了进一步的研究后,我认为不可能使用特定的文件名保存到data lake。这对我来说仍然很奇怪。如果你要走这条路,你应该使用
.coalesce(1)
而不是
.repartition(1)
减少节点之间的数据移动。重新分区将对所有节点的数据执行完全洗牌,然后再将其减少为单个分区。@DavidP您完全正确。我将相应地更改答案。