【问题标题】:Read local Parquet file without Hadoop Path API在没有 Hadoop Path API 的情况下读取本地 Parquet 文件
【发布时间】:2020-05-13 07:28:04
【问题描述】:

我正在尝试读取本地 Parquet 文件,但是我能找到的唯一 API 与 Hadoop 紧密耦合,并且需要 Hadoop Path 作为输入(即使指向本地文件)。

ParquetReader<GenericRecord> reader = AvroParquetReader.<GenericRecord>builder(file).build();
GenericRecord nextRecord = reader.read();

how to read a parquet file, in a standalone java code? 中最受欢迎的答案,但需要 Hadoop Path,现在已弃用,取而代之的是神秘的 InputFile。我能找到的InputFile 的唯一实现是HadoopInputFile,所以再次没有帮助。

在 Avro 中,这很简单:

DatumReader<GenericRecord> datumReader = new GenericDatumReader<>();
this.dataFileReader = new DataFileReader<>(file, datumReader);

(其中文件为java.io.File)。 Parquet 等价物是什么?

我要求答案中没有 Hadoop Path 依赖项,因为 Hadoop 会拖入臃肿和 jar 地狱,并且要求它来读取本地文件似乎很愚蠢。

为了进一步解释背景故事,我维护了一个小的 IntelliJ plugin,它允许用户将 Avro 文件拖放到窗格中以在表格中查看。这个插件目前是 5MB。如果我包含 Parquet 和 Hadoop 依赖项,它会膨胀到超过 50MB,并且doesn't even work


回答后附录

现在我已经让它工作了(感谢接受的答案),这是我的工作解决方案,它避免了严重依赖 Hadoop Path API 可能导致的所有烦人的错误:

【问题讨论】:

  • 很好的问题,非常感谢您提供的答案后附录代码。像魅力一样工作!

标签: java hadoop parquet


【解决方案1】:

如果确实无法避免不使用 Hadoop,您可以尝试使用 Spark 并在本地版本中运行它。可以在此处找到快速入门指南:https://spark.apache.org/docs/latest/index.html。下载,可以在这个链接下载:https://archive.apache.org/dist/spark/(找一个你喜欢的版本,总有一个没有hadoop的build,可惜压缩后的大小还在10-15M左右)。您还可以在 examples/src/main 找到一些 Java 示例。

之后,您可以像这样将文件作为 Spark Dataframe 读取

import org.apache.spark.api.java.*;
import org.apache.spark.api.java.function.*; 

SparkSession spark = SparkSession.builder().appName("Reducing dependecy by adding more dependencies").master("local[*]").getOrCreate();
        DataFrame parquet = sqlContext.read().parquet("C:/files/myfile.csv.parquet");
    parquet.show(20);

此解决方案确实满足问题中的原始条件。然而,它并没有回避这样一个事实,那就是它就像拐弯抹角(但地狱是的,这很有趣)。不过,它可能有助于开辟一种新的可能方法来解决这个问题。

【讨论】:

  • 很好的答案谢谢,这绝对是解决问题的新方法。我实际上已经快速尝试过了。在依赖spark-sql 和一些 Parquet 库之后,我的应用程序高达大约 93MB(我没有尝试排除事物或自己构建 Spark)。 Spark 绝对似乎是处理 Parquet 文件的首选解决方案,尽管正如您所说,它不是一个仅用于读取本地文件的轻量级解决方案。 Spark 还引入了自己的大量 jar hell 问题,这也是我希望避免使用 Hadoop 的原因之一。
【解决方案2】:

不幸的是,java parquet 实现并不独立于一些 hadoop 库。 make it easy to read and write parquet files in java without depending on hadoop 的 bugtracker 中存在一个现有问题,但似乎没有太大进展。添加了InputFile 接口以增加一点解耦,但许多实现 parquet 元数据部分的类以及所有压缩编解码器都存在于 hadoop 依赖项中。

我找到了another implementation of InputFile in the smile library,这可能比通过hadoop文件系统抽象更有效,但并不能解决依赖问题。

正如其他答案已经提到的,您可以为本地文件创建一个 hadoop Path 并毫无问题地使用它。

java.io.File file = ...
new org.apache.hadoop.fs.Path(file.toURI())

通过定义一些排除项可以大大减少hadoop引入的依赖树。我正在使用以下内容来减少臃肿(使用 gradle 语法):

compile("org.apache.hadoop:hadoop-common:3.1.0") {
    exclude(group: 'org.slf4j')
    exclude(group: 'org.mortbay.jetty')
    exclude(group: 'javax.servlet.jsp')
    exclude(group: 'com.sun.jersey')
    exclude(group: 'log4j')
    exclude(group: 'org.apache.curator')
    exclude(group: 'org.apache.zookeeper')
    exclude(group: 'org.apache.kerby')
    exclude(group: 'com.google.protobuf')
}

【讨论】:

  • 谢谢,这正是我添加赏金的原因 - 这是一个很好的答案。详细,有来源和解释,然后是对我有用的答案。 LocalInputFile 避免了 Path,因此不会触发我在 IntelliJ 插件中遇到的 ClassNotFoundException: Class org.apache.hadoop.fs.LocalFileSystem 错误。
【解决方案3】:

您可以为此使用ParquetFileReader

dependencies {
    compile group: 'org.apache.hadoop', name: 'hadoop-common', version: '3.2.0'
    compile group: 'org.apache.parquet', name: 'parquet-hadoop', version: '1.10.1'
}

你可以在这里指定你的本地目录路径

private static Path path = new Path("file:\\C:\\myfile.snappy.parquet");

ParquetFileReader r = new ParquetFileReader(conf, path, footer);

【讨论】:

  • 好的,但这确实使用了 Hadoop 依赖项和 Hadoop Path 对象,这是我希望避免的。也许我的问题有些模棱两可,所以我已经通过并试图使其更清楚。
  • 没有 Hadoop 路径也可以正常工作,您可以使用本地路径也有构造函数可用于传递 ParquetFileReader r = new ParquetFileReader(Inputfile, options)
  • 当我说“Hadoop 路径”时,我指的是任何使用 org.apache.hadoop.fs.Path 的 API。我还在我的问题中提到了InputFile,并且只能找到HadoopInputFile 的实现;如果您发现另一个不依赖于 Hadoop 的,那么我会接受它作为答案。
  • 请把我链接到构造函数new ParquetFileReader(new File("C:\\myfile.snappy.parquet") , options)
  • 又是一个org.apache.parquet.io.InputFilejava.io.File没有实现这个接口。您的示例无法编译。您不能将 java.io.File 传递给该构造函数。
猜你喜欢
  • 2020-07-22
  • 2019-12-21
  • 1970-01-01
  • 2014-04-29
  • 1970-01-01
  • 2018-12-19
  • 2015-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多