web-dev-qa-db-ja.com

ApacheのParquet Java API?

Apacheのparquet-mrプロジェクトを使用して、Javaを使用してプログラムでParquetファイルを読み書きしたいと思います。このAPIの使用方法に関するドキュメントが見つからないようです(ソースコードを調べて、その使用方法を確認する以外に)-そのようなドキュメントが存在するかどうか疑問に思っていますか?

9
Jason Evans

寄木細工のファイルの読み取りに関するブログ記事を書き( 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();
        }

    }
}
7
padmalcom

このリンクでドキュメントを見つけることができます: https://www.javadoc.io/doc/org.Apache.parquet/parquet-column/1.10.

左上のドロップダウンを使用して リスト ナビゲートする

3
Osama Khalifa

ドキュメントは少しまばらで、コードはやや簡潔にドキュメント化されています。それがあなたの選択肢であるならば、私はORCがはるかに扱いやすいと思いました。

以下のコードスニペットは、Avroインターフェイスを使用してParquetファイルをヘッダー行のあるCSVに変換します-ファイルにINT96(Hiveタイムスタンプ)タイプがあり(Avroインターフェイスの制限)、小数がバイト配列として出力される場合は失敗します。

必ず、parquet-avroライブラリのバージョン1.9.0以降を使用してください。そうしないと、ロギングが少し面倒になります。

        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();
1
Fat Freddie

これは@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;
    }
0
Sinan Erdem