我正在尝试读取一个本地Parquet文件,但是我能找到的唯一API是与Hadoop紧密耦合的,并且需要一个Hadoop Path
作为输入(即使是指向一个本地文件)。
ParquetReader<GenericRecord> reader = AvroParquetReader.<GenericRecord>builder(file).build();
GenericRecord nextRecord = reader.read();
是如何在独立的java代码中读取拼花文件?中最流行的答案,但是需要一个Hadoop Path
,现在已经不再推荐使用神秘的InputFile
了。我能找到的InputFile
的唯一实现是HadoopInputFile
,因此也没有任何帮助。
在Avro中,这是一个简单的例子:
DatumReader<GenericRecord> datumReader = new GenericDatumReader<>();
this.dataFileReader = new DataFileReader<>(file, datumReader);
(其中文件为java.io.File
)。什么是Parquet等价物?
我在答案中要求没有Hadoop Path
依赖,因为Hadoop拖拉在膨胀和罐子地狱,而且要求它来读取本地文件似乎很愚蠢。
为了进一步解释背景,我维护了一个小型IntelliJ插件,允许用户将Avro文件拖放到窗格中,以便在表中查看。这个插件目前是5MB。如果我包括Parquet和Hadoop依赖项,它会膨胀到超过50 it和甚至不起作用。
回覆增编
现在我已经让它正常工作了(感谢被接受的答案),下面是我的工作解决方案,它可以通过严重依赖Hadoop来避免所有烦人的错误:
发布于 2020-02-04 23:29:48
不幸的是,java parquet实现并不独立于某些hadoop库。在他们对在java中轻松地读取和编写parquet文件,而不依赖于hadoop。的追踪器中存在一个问题,但在这方面似乎没有多大进展。添加InputFile
接口是为了增加一些解耦,但是许多实现parquet元数据部分的类以及所有压缩编解码器都位于hadoop依赖项中。
我发现了在微笑库里,这可能比通过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')
}
发布于 2020-01-27 22:29:43
拼花-工具实用程序似乎是一个很好的起点。它确实有一些Hadoop依赖项,但与HDFS一样适用于本地文件(取决于Configuration
中的Configuration
)。如果您有许可限制(工具是Apache V2,与其他所有工具一样),您可能只需查看其中一个内容打印命令 (cat、head或cat)的源代码即可获得灵感。
我想,与您的Avro示例最接近的是使用ParquetFileReader。
Configuration conf = new Configuration();
Path path = new Path("/parquet/file/path");
ParquetMetadata footer = ParquetFileReader.readFooter(conf, path, ParquetMetadataConverter.NO_FILTER);
ParquetFileReader reader = new ParquetFileReader(conf, path, footer);
发布于 2020-02-05 02:56:47
如果不使用Hadoop的需求确实是不可避免的,您可以尝试Spark并在本地版本中运行它。可以在这里找到一个快速入门指南:https://spark.apache.org/docs/latest/index.html。要下载,您可以从以下链接下载:https://archive.apache.org/dist/spark/ (找到您喜欢的版本,总是有一个没有hadoop的版本)。不幸的是,压缩版本的大小仍然在10-15m左右)。您还可以在示例/src/main中找到一些Java示例。
在此之后,您可以像这样将文件读取为
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);
这个解决方案确实满足了问题的原始条件。然而,它并不缺少这样一个事实,那就是它就像在兜圈子(当然,这很有趣)。不过,这可能有助于开辟解决这一问题的新途径。
https://stackoverflow.com/questions/59939309
复制相似问题