Apache 依赖错误? org.apache.parquet.hadoop.codec.SnappyCodec 未找到 apache 库中的错误

Apache dependency bug? org.apache.parquet.hadoop.codec.SnappyCodec was not found Error in apache library

目前正在尝试在不使用 Spark 的情况下读取 Java 中的镶木地板文件。这是我目前所拥有的,基于 Adam Melnyk's blog post on the subject.

代码

        ParquetFileReader reader = ParquetFileReader.open(file);
        MessageType schema = reader.getFooter().getFileMetaData().getSchema();
        List<Type> fields = schema.getFields();
        PageReadStore pages;
-->     while ((pages = reader.readNextRowGroup()) != null) {
            long rows = pages.getRowCount();
            LOG.info("Number of rows: " + rows);
            MessageColumnIO columnIO = new ColumnIOFactory().getColumnIO(schema);
            RecordReader recordReader = columnIO.getRecordReader(pages, new GroupRecordConverter(schema));

            for (int i = 0; i < rows; i++) {
                SimpleGroup simpleGroup = (SimpleGroup) recordReader.read();
                simpleGroups.add(simpleGroup);
            }
        }

(注意箭头是在我的代码中抛出错误的第(167)行)

错误信息

org.apache.parquet.hadoop.BadConfigurationException: Class org.apache.parquet.hadoop.codec.SnappyCodec was not found
        at org.apache.parquet.hadoop.CodecFactory.getCodec(CodecFactory.java:243)
        at org.apache.parquet.hadoop.CodecFactory$HeapBytesDecompressor.<init>(CodecFactory.java:96)
        at org.apache.parquet.hadoop.CodecFactory.createDecompressor(CodecFactory.java:212)
        at org.apache.parquet.hadoop.CodecFactory.getDecompressor(CodecFactory.java:201)
        at org.apache.parquet.hadoop.CodecFactory.getDecompressor(CodecFactory.java:42)
        at org.apache.parquet.hadoop.ParquetFileReader$Chunk.readAllPages(ParquetFileReader.java:1519)
        at org.apache.parquet.hadoop.ParquetFileReader$Chunk.readAllPages(ParquetFileReader.java:1402)
        at org.apache.parquet.hadoop.ParquetFileReader.readChunkPages(ParquetFileReader.java:1023)
        at org.apache.parquet.hadoop.ParquetFileReader.readNextRowGroup(ParquetFileReader.java:928)
        at [myClassPath]([myClass].java:167)

依赖关系

   <groupId>org.apache.hadoop</groupId>
   <artifactId>hadoop-hdfs</artifactId>
   <version>3.1.1.3.1.4.0-315</version>
 </dependency>
 <dependency>
   <groupId>org.apache.hadoop</groupId>
   <artifactId>hadoop-common</artifactId>
   <version>3.1.1.3.1.4.0-315</version>
 </dependency>
 <dependency>
   <groupId>org.apache.spark</groupId>
   <artifactId>spark-launcher_2.12</artifactId>
   <version>3.0.0-preview2</version>
 </dependency>
 <dependency>
   <groupId>org.apache.parquet</groupId>
   <artifactId>parquet-avro</artifactId>
   <version>1.12.0</version>
 </dependency>

似乎无法从 CodecFactory class 中找到 SnappyCodec class,但我查看了我引用的库并且 class 在那里: referenced_libraries

CodecFactory 应该能够识别 SnappyCodec class。有什么建议吗? 谢谢

找到解决方案。

所以问题是 SnappyCodec class 被我为我的应用程序配置的 maven 阴影插件遮蔽了。

我是在用 maven 打包 jar,用 WinZip 打开那个 jar,检查打包后的 jar 的编解码器目录(我发现 SanppyCodec.class 不再存在)后才意识到这一点的。

解决方案是我需要将以下过滤器添加到我的 maven 阴影插件的配置中:

<filter>
    <artifact>org.apache.parquet:parquet-hadoop</artifact>
    <includes>
          <include>**</include>
    </includes>
</filter>
<filter>
    <artifact>org.apache.parquet:parquet-column</artifact>
    <includes>
          <include>**</include>
    </includes>
</filter>
<filter>
    <artifact>org.apache.parquet:parquet-encoding</artifact>
    <includes>
          <include>**</include>
    </includes>
</filter>

基本上,maven-shade 是从 parquet-hadoop 工件中看似随机 classes 进行着色,因此通过添加 <include> 过滤器,maven-shade 没有对任何 [=30] 进行着色=]es 在其中,因此不会在其中遮蔽 SnappyCodec.class 文件。

这样做之后,我需要添加其他两个过滤器,因为通过在 parquet-hadoop 工件上使用 <include> 标记,它会排除所有其他 parquet-* 工件被添加到编译的 jar .因此,我需要明确地告诉它也包括 parquet-column 和 parquet-encoding,因为我的应用程序在这些工件中使用了其他一些 classes。

此配置意味着 maven-shader 不会触及这三个工件,这意味着编译时之前存在于这些工件中的所有 class 将在 compiling/packaging 之后与 Maven 一起保留在那里(因此,会在运行时存在,而之前不存在,从而导致原始错误)。太棒了!