【问题标题】:Documentation for Apache's Parquet Java API?Apache Parquet Java API 的文档?
【发布时间】:2017-05-02 17:39:31
【问题描述】:

我想使用 Apache 的 parquet-mr 项目通过 Java 以编程方式读/写 Parquet 文件。我似乎找不到任何关于如何使用这个 API 的文档(除了查看源代码并查看它是如何使用的)——只是想知道是否存在任何这样的文档?

【问题讨论】:

  • 最好通过单元测试,我还找不到任何文档。 :)
  • 意思是你可以通过this作为样本。
  • 谢谢@Krishas,这是一个开始

标签: parquet


【解决方案1】:

我写了一篇关于读取 parquet 文件的博客文章 (http://www.jofre.de/?p=1459),并提出了以下解决方案,它甚至能够读取 INT96 字段。

您需要以下 maven 依赖项:

<dependencies>
  <dependency>
    <groupId>org.apache.parquet</groupId>
    <artifactId>parquet-hadoop</artifactId>
    <version>1.9.0</version>
  </dependency>
  <dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>2.7.0</version>
  </dependency>
</dependencies>

代码基本上是:

public class Main {

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

    private static void printGroup(Group g) {

        int fieldCount = g.getType().getFieldCount();
        for (int field = 0; field < fieldCount; field++) {
            int valueCount = g.getFieldRepetitionCount(field);

            Type fieldType = g.getType().getType(field);
            String fieldName = fieldType.getName();

            for (int index = 0; index < valueCount; index++) {
                if (fieldType.isPrimitive()) {
                    System.out.println(fieldName + " " + g.getValueToString(field, index));
                }
            }
        }

    }

    public static void main(String[] args) throws IllegalArgumentException {

        Configuration conf = new Configuration();

        try {
            ParquetMetadata readFooter = ParquetFileReader.readFooter(conf, path, ParquetMetadataConverter.NO_FILTER);
            MessageType schema = readFooter.getFileMetaData().getSchema();
            ParquetFileReader r = new ParquetFileReader(conf, path, readFooter);

            PageReadStore pages = null;
            try {
                while (null != (pages = r.readNextRowGroup())) {
                    final long rows = pages.getRowCount();
                    System.out.println("Number of rows: " + rows);

                    final MessageColumnIO columnIO = new ColumnIOFactory().getColumnIO(schema);
                    final RecordReader<Group> recordReader = columnIO.getRecordReader(pages, new GroupRecordConverter(schema));
                    for (int i = 0; i < rows; i++) {
                        final Group g = recordReader.read();
                        printGroup(g);

                        // TODO Compare to System.out.println(g);
                    }
                }
            } finally {
                r.close();
            }
        } catch (IOException e) {
            System.out.println("Error reading parquet file.");
            e.printStackTrace();
        }

    }
}

【讨论】:

  • 当您尝试系统输出值时,递归调用在哪里?在我看来,如果类型不是原始类型,则代码不会对该字段执行任何操作。
  • 但是你认为我们应该使用 org.apache.parquet.example 包中的类来读取 parquet 文件吗?
【解决方案2】:

您可以在此链接中找到文档:https://www.javadoc.io/doc/org.apache.parquet/parquet-column/1.10.0

使用左上角下拉菜单list 进行导航

【讨论】:

    【解决方案3】:

    文档有点稀疏,代码的文档也比较简洁。如果您愿意,我发现 ORC 更容易使用。

    下面的代码 sn-p 使用 Avro 接口将 Parquet 文件转换为带有标题行的 CSV - 如果文件中有 INT96(Hive 时间戳)类型(Avro 接口限制)并且小数出现,它将失败作为一个字节数组。

    确保您使用 1.9.0 或更高版本的 parquet-avro 库,否则日志记录会有点混乱。

            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(java.io.FileDescriptor.out), "ASCII"));
    
            ParquetReader<GenericRecord> reader = AvroParquetReader.<GenericRecord>builder(path).build();
    
            Schema sc = null;
            List<Field> fields = null;
            for(long i = 0; i < lines; i++)  {
                GenericRecord result = reader.read();
                if(result == null)  {
                    break;
                }
    
                if(i == 0)  {
                    sc = result.getSchema();
                    fields = sc.getFields();
                    if(header)  {       // print header out?
                        for(int j = 0; j < fields.size(); j++)  {
                            if(j != 0)  {
                                out.write(",");
                            }
                            out.write(fields.get(j).name());
                        }
                        out.newLine();
                    }
                }
    
                for(int j = 0; j < fields.size(); j++)  {
                    if(j != 0)  {
                        out.write(",");
                    }
                    Object o = result.get(j);
                    if(o != null)  {
                        String v = o.toString();
                        if(!v.equals("null"))  {
                            out.write("\"" + v + "\"");
                        }
                    }
                }
                out.newLine();
            }
            out.flush();
            reader.close();
    

    【讨论】:

    • 感谢@FatFreddie 的回答,这很有帮助,但我真的在寻找parquet-mr 库的文档,而不是parquet-avro。
    • 据我了解,Parquet-mr 是 Parquet 的 Java 接口。在其中你有各种各样的接口...... parquet-avro parquet-thrift parquet-protobuf 等还有 parquet-tools (CLI 实用程序)使用的“简单”接口 - 在存储库中搜索 CatCommand.java。简单的界面很容易上手,但据我所知,它不支持读取模式,而且我看到 cmets 只是用作示例界面,所以我停止使用它。 Avro 接口确实支持读取模式并且通常工作得很好,但不支持 INT96。
    【解决方案4】:

    这是对@padmalcom 答案的补充。该答案的代码只是缺少嵌套值的递归操作。相反,我返回一个 JSONObject,如何打印它取决于开发人员等。我使用下面的函数而不是他的 printGroup() 函数。 (感谢原创灵感)

    private static JSONObject convertParquetGroupToJSONObject(final Group g) {
            JSONObject jsonObject = new JSONObject();
    
            int fieldCount = g.getType().getFieldCount();
            for (int field = 0; field < fieldCount; field++) {
                int valueCount = g.getFieldRepetitionCount(field);
                Type fieldType = g.getType().getType(field);
                String fieldName = fieldType.getName();
                for (int index = 0; index < valueCount; index++) {
                    if (fieldType.isPrimitive()) {
                        try {
                            jsonObject.put(fieldName, g.getValueToString(field, index));
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    } else{
                        try {
                            jsonObject.put(fieldName, convertParquetGroupToJSONObject(g.getGroup(field, index)));
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            return jsonObject;
        }
    

    【讨论】:

    猜你喜欢
    • 2017-11-24
    • 2012-02-07
    • 2017-09-06
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多