Apache Parquet Java API的文档?

时间:2017-05-02 17:39:32

标签: parquet

我想使用Apache的parquet-mr项目以Java编程方式读/写Parquet文件。我似乎无法找到有关如何使用此API的任何文档(除了浏览源代码并查看它是如何使用的) - 只是想知道是否存在任何此类文档?

4 个答案:

答案 0 :(得分:7)

我写了一篇关于阅读镶木地板文件(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();
        }

    }
}

答案 1 :(得分:3)

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

使用左上方的下拉列表list进行导航

答案 2 :(得分:1)

文档有点稀疏,代码有点简洁。我发现ORC更容易使用,如果这是你的选择。

下面的代码片段使用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();

答案 3 :(得分:0)

这是@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;
    }