thrift、序列化与parquet读取

来源:互联网 发布:淘宝客推广链接 编辑:程序博客网 时间:2024/05/16 12:28

parquet是一种常见的列式存储格式,普通的parquet文件可以用java中的ParquetReader<Group>来读取,在存储格式较为简单时,可以通过Group.get×××可以获得相应列的数据,获得相应json格式数据(手动拼接)的代码如下:

// 获取字段信息ParquetMetadata readFooter = ParquetFileReader.readFooter(fs.getConf(), filePath,ParquetMetadataConverter.NO_FILTER);MessageType schema = readFooter.getFileMetaData().getSchema();List<Type> colTypes = schema.getFields();ParquetReader<Group> reader = ParquetReader.builder(new GroupReadSupport(), filePath).withConf(fs.getConf()).build();Group recordData = reader.read();// 先拼成json格式while (recordData != null) {StringBuilder builder = new StringBuilder();builder.append("{");for (int j = 0; j < colTypes.size(); j++) {// 获得字段名和值String columnName = colTypes.get(j).getName();String value = recordData.getValueToString(j, 0);builder.append("\"" + columnName + "\":\"" + value+ "\"");builder.append(j == colTypes.size() - 1 ? "}" : ",");}buffers.add(builder.toString());recordData = reader.read();}

但当文件通过Thrift进行序列化(自定义的serialization.class)后,直接Group.toString()查看获取到的整个字段内容,发现它为如下格式:

root1

key1:val1

key2

subkey1:subval1

key3

root2

root3

...

这种格式依然可以通过group读取,但在一些特定字段不存在时,get方法会抛出异常,并且代码看起来非常凌乱,上文的数据样例,如果想要获取subval1的值,假设字段类型为String,则需要group.getGroup("root1",0).getGroup("key2",0).getString("subkey1",0),这样的方式,其中,get方法的第二个参数为第k个名称为var的数据,同时,还需要catch住因为中间字段不存在的情况而抛出的异常。


因此,为了避免不必要的麻烦(当然,如果你仅仅需要一个数据,或是整个group都需要,当我没说),通过Thrift序列化的数据,可以通过ThriftParquetReader进行反序列化读取,直接将内容读取至对应的class中。方法如下:

ParquetReader<T> parquetReader = ThriftParquetReader.<T> build(filePath).withThriftClass(<ClassT>).build();T objectT = parquetReader.read();


其中,Class T需要实现的接口为TBase<?,?>,当然,由于你使用的是serialization.class,所以默认不需要考虑这个问题,通过read后,你就可以愉快的通过T中的各种方法获取对应字段而不用担心再抛异常啦~ 读取到末尾时,read()会返回一个null,并且在用完之后,记得把它close掉哦,还有,ThriftParquetReader在package parquet.thrift和org.apache.parquet.thrift中都有,此处我们需要的是后者,不要导错包哦~