dataFrame.coalesce(1).write().save("path")
有时仅写入_SUCCESS和._SUCCESS.crc文件,即使在非空输入DataFrame
上也没有预期的* .csv.gz
文件保存代码:
private static void writeCsvToDirectory(Dataset<Row> dataFrame, Path directory) {
dataFrame.coalesce(1)
.write()
.format("csv")
.option("header", "true")
.option("delimiter", "\t")
.option("codec", "org.apache.hadoop.io.compress.GzipCodec")
.mode(SaveMode.Overwrite)
.save("file:///" + directory);
}
文件获取代码:
static Path getTemporaryCsvFile(Path directory) throws IOException {
String glob = "*.csv.gz";
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory, glob)) {
return stream.iterator().next();
} catch (NoSuchElementException e) {
throw new RuntimeException(getNoSuchElementExceptionMessage(directory, glob), e);
}
}
文件获取错误示例:
java.lang.RuntimeException: directory /tmp/temp5889805853850415940 does not contain a file with glob *.csv.gz. Directory listing:
/tmp/temp5889805853850415940/_SUCCESS,
/tmp/temp5889805853850415940/._SUCCESS.crc
我依靠这种期望,有人可以向我解释为什么会这样吗?
答案 0 :(得分:2)
输出文件(必须按逻辑)至少应包含标题行和一些数据行。但是他根本不存在
此评论有点误导。根据Github上的代码,只有在Dataframe为空并且不会产生SUCCESS
文件时,才会发生这种情况。考虑到这些文件存在-数据框不为空,并且触发了代码中的writeCsvToDirectory
。
我有几个问题:
SUCCESS
文件的时间戳是否已更新? 我的两个主要嫌疑人是:
coalesce(1)
-如果您有很多数据,则可能会失败SaveMode.Overwrite
-我觉得这些成功文件位于以前运行的那个文件夹中答案 1 :(得分:1)
选择写入csv文件取决于您的存储。 如果您在hdfs上写就可以了。但是,无论何时决定写入本地文件系统,都必须注意不要在驱动程序本地文件系统中写入任何内容,并且数据将位于worker的文件系统中,并且应该在worker的存储中找到它们。< / p>
两个解决方案:
设置本机本地[NUMBER_OF_CORES],您可以通过--master local[10]
配置
将数据写入s3,hdfs等分布式文件系统中...
答案 2 :(得分:0)
我自己的解决方案解决了这个问题。
我将.save("file://"
替换为hadoopFileSystem.copyToLocalFile
问题是.save("file://
仅适用于SparkSession.builder().master("local")
,其中hdfs://
是由上级file://
模拟的。
我在理论上可能是错的,但确实有效。
static Path writeCsvToTemporaryDirectory(Dataset<Row> dataFrame) throws IOException {
String temporaryDirectoryName = getTemporaryDirectoryName();
writeCsvToDirectory(dataFrame, temporaryDirectoryName, sparkContext);
return Paths.get(temporaryDirectoryName);
}
static void writeCsvToDirectory(Dataset<Row> dataFrame, String directory) throws IOException {
dataFrame.coalesce(1)
.write()
.option("header", "true")
.option("delimiter", "\t")
.option("codec", "org.apache.hadoop.io.compress.GzipCodec")
.mode(SaveMode.Overwrite)
.csv(directory);
FileSystem hadoopFileSystem = FileSystem.get(sparkContext.hadoopConfiguration());
hadoopFileSystem.copyToLocalFile(true,
new org.apache.hadoop.fs.Path(directory),
new org.apache.hadoop.fs.Path(directory));
}
static Path getTemporaryCsvFile(Path directory) throws IOException {
String glob = "*.csv.gz";
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory, glob)) {
return stream.iterator().next();
} catch (NoSuchElementException e) {
throw new RuntimeException(getNoSuchElementExceptionMessage(directory, glob), e);
}
}
Path temporaryDirectory = writeCsvToTemporaryDirectory(dataFrame);
Path temporaryFile = DataFrameIOUtils.getTemporaryCsvFile(temporaryDirectory);
try {
return otherStorage.upload(temporaryFile, name, fields).join();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
} finally {
removeTemporaryDirectory(temporaryDirectory);
}