FileInputStream/FileOutputStream 与 FSDataInputStream/FSDataOutputStream 之间的区别是什么以及我们将在哪里使用它们

What is the difference between FileInputStream/FileOutputStream Vs FSDataInputStream/FSDataOutputStream and where we will use them

我想了解 FileInputStream 与 FSDataInputStream 和 FileOutputStream 与 FSDataOutputStream 之间的区别。

我正在尝试从 S3 存储桶中读取文件并应用一些格式更改,然后想将其写入 spark java 应用程序中的另一个 S3 存储桶

我很困惑是否需要使用 FileInputStream 或 FSDataInputStream 来读取文件以及如何使用 FileOutputStream 或 FSDataOutputStream 将它们写入 S3 存储桶。

有人可以举例说明我们需要如何以及在何处适当地使用它们吗?

两者都可以,看你需要什么。

它们都只是流实现。最终你要做的是从一个桶中获取输入流并将其写入另一个桶的输出流。

FileInputStreamFileOutputStream具体组件,它们提供从映射文件读取和写入流的功能。

FSDataInputStreamFSDataOutputStream 是输入流的 具体装饰器 。这意味着使用功能提供或修饰输入流,例如读取和写入原语以及提供缓冲流。

选哪个?您需要 FSDataOutputStream 和 FSDataInputStream 提供的装饰吗? FileInputStream 和 FileOutputStream 是否足够?

就个人而言,我希望使用 ReadersWriters,如下所示:

private final AmazonS3 amazonS3Client = AmazonS3ClientBuilder.standard().build();

private Collection<String> loadFileFromS3() {
    try (final S3Object s3Object = amazonS3Client.getObject(BUCKET_NAME,
                                                            FILE_NAME);
        final InputStreamReader streamReader = new InputStreamReader(s3Object.getObjectContent(), StandardCharsets.UTF_8);
        final BufferedReader reader = new BufferedReader(streamReader)) {
        return reader.lines().collect(Collectors.toSet());
    } catch (final IOException e) {
        log.error(e.getMessage(), e)
        return Collections.emptySet();
    }
}

FSDataInputStreamFSDataOutputStream 是 类 在 hadoop-common

FSDataInputStream

FSDataInputStream 添加高性能 API,用于将特定偏移处的数据读取到字节数组 (PositionedReadable) 或字节缓冲区中。这些被广泛用于图书馆读取文件,其中读取不是顺序的,更随机的 IO。 parquet、orc 等。文件系统实现通常提供这些的高效实现。这些 api 与简单文件复制无关,除非您真的在尝试获得最大性能,已将同一源文件打开到多个流并在它们之间并行获取块。 Distcp 就是这样做的,这就是为什么如果你努力尝试它会导致网络过载的原因。

完整规范,包括 PositionedReadable:fsdatainputstream

FSDataOutputStream

FSDataOutputStream 并没有比正常的 DataOutputStream 增加多少;最重要的接口是 Syncable,其 hflush 和 hsync 调用对持久性有特定的保证,如“当它们 return 时,数据已被持久化到 HDFS 或其他文件系统,对于 hsync,所有磁盘方式”。如果您正在实施像 HBase 这样的数据库,您需要这些和那些保证。如果你不是,那么你 真的 不会。在最近的 hadoop 版本中,在写入 S3 时尝试使用它们只会记录一条警告消息,告诉您停止它。毕竟它不是真正的文件系统。

完整规范,包括可同步的:outputstream

大规模复制 spark 中的文件

如果你想在 spark 中高效地复制文件,请打开带有几 MB 缓冲区的源文件和目标文件,读入缓冲区,然后将其写回。您可以将这项工作分布在整个集群中以获得更好的并行性,如本例所示:https://github.com/hortonworks-spark/cloud-integration/blob/master/spark-cloud-integration/src/main/scala/com/cloudera/spark/cloud/applications/CloudCp.scala

  1. 如果您只想复制一个或两个文件,只需在单个进程中执行,也可以在多线程中执行。
  2. 如果你真的在寻求针对 s3 的性能,请获取要复制的文件列表,首先安排最大的几个文件,这样它们就不会把你拖到最后,然后随机化列表的其余部分以避免创建热点在 s3 存储桶中。