使用parquet-hadoop.jar包解析hive parquet文件时,遇到FIXED_LEN_BYTE_ARRAY转换为Decimal 以及 INT96转换为timestamp问题
在使用parquet-hadoop.jar包解析parquet文件时,遇到decimal类型的数据为乱码,具体解决方法如下:
使用parquet-Hadoop.jar解析httpfs服务提供的parquet文件,代码如下:
@Test
public void httpfsReadHiveParquetFile() throws Exception { Path path = new Path("webhdfs://s128:14000/wbd_test/parq1.0.parq");
Configuration conf = new Configuration();
conf.set("fs.webhdfs.impl", WebHdfsFileSystem.class.getName());
Map<String, String> urlParams = new HashMap<>();
urlParams.put("user.token", "7hmsNJIget0eGO5maKQ=sfds");
conf.set(WebHdfsFileSystem.HTTPFS_URL_PARAM, JSON.toJSONString(urlParams));
FileSystem fs = path.getFileSystem(conf); FileStatus fileStatus = fs.getFileStatus(path); InputFile inputFile = HadoopInputFile.fromStatus(fileStatus, conf);
GroupReadSupport readSupport = new GroupReadSupport();
ParquetReader.Builder<Group> reader= ParquetReader.read(inputFile);
reader.withConf(conf);
ParquetReader<Group> build=reader.build(); Group line=null;
line=build.read(); Map<String,String> fieldTypeMap = new HashMap<String, String>(); if (line != null){
List<Type> typeList = line.getType().getFields();
ParquetInputFormat inputFormat = new ParquetInputFormat();
for(Type type : typeList){
System.out.print(type.getName()+"("+type.asPrimitiveType().getPrimitiveTypeName().name()+")\t\t");
}
System.out.println();
System.out.println("-----------------------------------------------------------------------------------------------------------");
do{
for (Type type : typeList){
System.out.print(converterType2Java(line, type)+"\t\t");
}
System.out.println();
}while ((line=build.read())!=null);
} System.out.println("It is over !"); } public static String converterType2Java(Group line, Type type) {
String value = null;
String fieldType = type.asPrimitiveType().getPrimitiveTypeName().name();
String fieldName = type.getName();
int repetition = line.getFieldRepetitionCount(type.getName());
if (repetition == 0){
return value;
} switch (fieldType){
case "BOOLEAN":
value = String.valueOf(line.getBoolean(fieldName, 0));
break;
case "INT32":
value = String.valueOf(line.getInteger(fieldName, 0));
break;
case "INT64":
value = String.valueOf(line.getLong(fieldName, 0));
break;
case "INT96":
value = String.valueOf(getTimestampMillis(line.getInt96(fieldName, 0)));
break;
case "FLOAT":
value = String.valueOf(line.getFloat(fieldName, 0));
break;
case "DOUBLE":
value = String.valueOf(line.getDouble(fieldName, 0));
break;
case "FIXED_LEN_BYTE_ARRAY":
if (type.getOriginalType() != null && type.getOriginalType().name().equals("DECIMAL")){
value = String.valueOf(binaryToDecimal(type.asPrimitiveType().getDecimalMetadata().getPrecision(), type.asPrimitiveType().getDecimalMetadata().getScale(), line.getBinary(fieldName, 0).getBytes()));
int precision = type.asPrimitiveType().getDecimalMetadata().getPrecision();
int scale = type.asPrimitiveType().getDecimalMetadata().getScale();
BigDecimal decimalValue = binaryToDecimal(precision, scale, line.getBinary(fieldName, 0).getBytes());
String precisionFormat = String.join("", Collections.nCopies(precision-1, "#"));
String scaleFrmat = String.join("", Collections.nCopies(scale,"0"));
String format = precisionFormat + "0."+ scaleFrmat;
DecimalFormat decimalFormat = new DecimalFormat(format); value = decimalFormat.format(decimalValue);
}
break;
case "BINARY":
value = line.getString(fieldName, 0);
break;
default:
value = line.getString(fieldName, 0);
}
return value;
} public static long getTimestampMillis(Binary timestampBinary)
{
if (timestampBinary.length() != 12) {
return 0;
}
byte[] bytes = timestampBinary.getBytes(); // little endian encoding - need to invert byte order
long timeOfDayNanos = Longs.fromBytes(bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0]);
int julianDay = Ints.fromBytes(bytes[11], bytes[10], bytes[9], bytes[8]); return julianDayToMillis(julianDay) + (timeOfDayNanos / NANOS_PER_MILLISECOND);
} private static long julianDayToMillis(int julianDay)
{
return (julianDay - JULIAN_EPOCH_OFFSET_DAYS) * MILLIS_IN_DAY;
} static BigDecimal binaryToDecimal(int precision, int scale, byte[] bytes) {
/*
* Precision <= 18 checks for the max number of digits for an unscaled long,
* else treat with big integer conversion
*/
if (precision <= 18) { int start = 0;//buffer.arrayOffset() + buffer.position();
int end = bytes.length; //buffer.arrayOffset() + buffer.limit();
long unscaled = 0L;
int i = start;
while ( i < end ) {
unscaled = ( unscaled << 8 | bytes[i] & 0xff );
i++;
}
int bits = 8*(end - start);
long unscaledNew = (unscaled << (64 - bits)) >> (64 - bits);
BigDecimal result;
if (unscaledNew <= -pow(10,18) || unscaledNew >= pow(10,18)) {
result = new BigDecimal(unscaledNew);
// System.out.println(result);
} else {
result = BigDecimal.valueOf(unscaledNew / pow(10,scale));
// System.out.println(result);
}
return result;
} else {
BigDecimal result = new BigDecimal(new BigInteger(bytes), scale);
// System.out.println(result);
return result;
}
}
parquet文件timestamp类型实际为INT96类型,decimal实际为FIXED_LEN_BYTE_ARRAY二进制类型,要想得到原来的数据,都需要进行转换,在网上很少能找到相关问题,希望对其他人有所帮助
使用parquet-hadoop.jar包解析hive parquet文件时,遇到FIXED_LEN_BYTE_ARRAY转换为Decimal 以及 INT96转换为timestamp问题的更多相关文章
- java jar包解析:打包文件,引入文件
java jar包解析:打包文件,引入文件 cmd下: jar命令:package包打包 javac命令:普通类文件打包 Hello.java: package org.lxh.demo; publi ...
- Spring (3.2.4) 常用jar 包解析
Spring (3.2.4) 常用jar 包解析 基本jar包 spring-aop-3.2.4.RELEASE.jar spring-aspects-3.2.4.RELEASE.jar spring ...
- 在eclipse中导入hadoop jar包,和必要时导入源码包。
1. 解药hadoop包 1, C:\hadoop-2.7.2\share\hadoop 提取出所有的 jar 包, 到 _lib 文件夹下 2,将有含有source 名称的jar包 剪切出来 3, ...
- idea导入hadoop jar包
hadoop jar包 在hadoop安装目录下,找到share\hadoop目录,搜索jar,全选,然后在安装目录新建_jar文件夹,将所有的jar包拷进去 idea添加jar包 在Project ...
- html或者jsp页面引用jar包中的js文件
一,页面上引用jar包中的js文件的方法 使用java web框架AppFuse的时候发现,jquery.bootstrap等js框架都封装到jar包里面了.这些js文件通过一个wro4j的工具对其进 ...
- springmvc 项目完整示例07 设置配置整合springmvc springmvc所需jar包springmvc web.xml文件配置
前面主要是后台代码,spring以及mybatis的整合 下面主要是springmvc用来处理请求转发,展现层的处理 之前所有做到的,完成了后台,业务层和持久层的开发完成了 接下来就是展现层了 有很多 ...
- maven本地安装jar包同时生成pom文件
maven 本地安装jar包:mvn install:install-file -Dfile=本地路径/ojdbc12.jar -DgroupId=com.oracle -DartifactId=oj ...
- 【解惑】深入jar包:从jar包中读取资源文件
[解惑]深入jar包:从jar包中读取资源文件 http://hxraid.iteye.com/blog/483115 TransferData组件的spring配置文件路径:/D:/develop/ ...
- java 从jar包中读取资源文件
在代码中读取一些资源文件(比如图片,音乐,文本等等),在集成环境(Eclipse)中运行的时候没有问题.但当打包成一个可执行的jar包(将资源文件一并打包)以后,这些资源文件找不到,如下代码: Jav ...
随机推荐
- 剑指offer-字符串的排列
题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 输入描述: 输 ...
- 【java多线程】多线程中的long和double
在看一些代码的时候,会发现在定义long型和double型的变量时,会在前面加上volatile关键字,当然也会看到在其它原子类型的变量前加上这个关键字,但这里要说的还是有区别的. 在java中,ja ...
- docker Swarm mode集群
基本概念 Swarm 是使用 SwarmKit 构建的 Docker 引擎内置(原生)的集群管理和编排工具. 使用 Swarm 集群之前需要了解以下几个概念. 节点 运行 Docker 的主机可以主动 ...
- 一、基础篇--1.2Java集合-HashMap和HashSet的区别
HashMap和HashSet的区别 1.HashMap实现的是Map接口,HashSet实现的是Set接口 2.结构不一样,一个存储的是键值对,一个存储的是对象 3.HashMap存储的值可能相同 ...
- springboot备忘
1.springboot中有ApplicationRunner类,如果项目中的启动类名称也是ApplicationRunner,单元测试时需要注意:import不要import到springboot的 ...
- Spring Annotations
@Bean 这是一个方法注解,作用是实例化一个Bean并使用该方法的名臣命名.
- k8s部署01-----what is k8s?
简介 1.Kubernetes代码托管在GitHub上:https://github.com/kubernetes/kubernetes/. 2.Kubernetes是一个开源的,容器集群管理系统,K ...
- echarts修改X,Y轴上的颜色
分为2.0和3.0 一.2.0 修改的代码: x轴: xAxis : [ { type : 'category', data : ['<30','30-','40-','50-','60-', ...
- 深入理解AlexNet网络
原文地址:https://blog.csdn.net/luoluonuoyasuolong/article/details/81750190 AlexNet论文:<ImageNet Classi ...
- Mysql中用SQL增加、删除、修改(包括字段长度/注释/字段名)总结
转: Mysql中用SQL增加.删除.修改(包括字段长度/注释/字段名)总结 2018年09月05日 10:14:37 桥Dopey 阅读数:1830 版权声明:本文为博主原创文章,未经博主允许不 ...