thrift、序列化与parquet读取

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

// 获取字段信息
				ParquetMetadata readFooter = ParquetFileReader.readFooter(
						fs.getConf(), filePath,
						ParquetMetadataConverter.NO_FILTER);
				MessageType schema = readFooter.getFileMetaData().getSchema();
				List colTypes = schema.getFields();

				ParquetReader 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 parquetReader = ThriftParquetReader
										. build(filePath)
										.withThriftClass()
										.build();
								T objectT = parquetReader.read();


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



你可能感兴趣的:(学习笔记)