在使用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问题的更多相关文章

  1. java jar包解析:打包文件,引入文件

    java jar包解析:打包文件,引入文件 cmd下: jar命令:package包打包 javac命令:普通类文件打包 Hello.java: package org.lxh.demo; publi ...

  2. 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 ...

  3. 在eclipse中导入hadoop jar包,和必要时导入源码包。

    1. 解药hadoop包 1, C:\hadoop-2.7.2\share\hadoop  提取出所有的 jar 包, 到 _lib 文件夹下 2,将有含有source 名称的jar包 剪切出来 3, ...

  4. idea导入hadoop jar包

    hadoop jar包 在hadoop安装目录下,找到share\hadoop目录,搜索jar,全选,然后在安装目录新建_jar文件夹,将所有的jar包拷进去 idea添加jar包 在Project ...

  5. html或者jsp页面引用jar包中的js文件

    一,页面上引用jar包中的js文件的方法 使用java web框架AppFuse的时候发现,jquery.bootstrap等js框架都封装到jar包里面了.这些js文件通过一个wro4j的工具对其进 ...

  6. springmvc 项目完整示例07 设置配置整合springmvc springmvc所需jar包springmvc web.xml文件配置

    前面主要是后台代码,spring以及mybatis的整合 下面主要是springmvc用来处理请求转发,展现层的处理 之前所有做到的,完成了后台,业务层和持久层的开发完成了 接下来就是展现层了 有很多 ...

  7. maven本地安装jar包同时生成pom文件

    maven 本地安装jar包:mvn install:install-file -Dfile=本地路径/ojdbc12.jar -DgroupId=com.oracle -DartifactId=oj ...

  8. 【解惑】深入jar包:从jar包中读取资源文件

    [解惑]深入jar包:从jar包中读取资源文件 http://hxraid.iteye.com/blog/483115 TransferData组件的spring配置文件路径:/D:/develop/ ...

  9. java 从jar包中读取资源文件

    在代码中读取一些资源文件(比如图片,音乐,文本等等),在集成环境(Eclipse)中运行的时候没有问题.但当打包成一个可执行的jar包(将资源文件一并打包)以后,这些资源文件找不到,如下代码: Jav ...

随机推荐

  1. 使用IDEA集成Spring框架时右下角警戒

    反正看到报错就不爽,就要去解决它 这个警戒的意思大概就是: spring配置检查 找到未映射的Spring配置文件. 请配置Spring的Facet. 那这玩意怎么配置? 点击IDEA右上角的Proj ...

  2. Mybatis 实体类使用@Accessors(chain = true)注解时,对应的mapper xml 报错

    去掉这个注解就行了 应该是 mybatis 会调用实体类的 getter  setter 方法, 返回值可能会有所影响

  3. Mac Vmware NAT模式

    1.NAT模式原理 2.MAC上关于Vmware的配置 1)/Library/Preferences/VMware Fusion/networking MacBookPro:~ zhangxm$ vi ...

  4. MVC中上传文件

    与asp.net中几乎一样,使用表单提交的方式上传文件(如果是使用了第三方插件的话,那么就另当别论) @{ ViewBag.Title = "Index"; Layout = nu ...

  5. java加密算法相关

    简介 RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.1987年首次公布,当 ...

  6. Java-内存模型(JSR-133)

    Java 内存模型(Java Memory Model,JMM)看上去和 Java 内存结构(JVM 运行时内存结构)差不多,但这两者并不是一回事.JMM 并不像 JVM 内存结构一样是真实存在的,它 ...

  7. swift--【do..catch与try,try?,try!】

    throws抛出异常, 那么就必须通过try来处理 try : 标准的处理方式, 该方式必须结合do catch来处理 try? :告诉系统可能有错, 也可能没错, 如果发生错误, 那么返回nil, ...

  8. 前端Ajax跨域解决方案

    业务场景: 前后端分离需要对接数据接口. 接口测试是在postman做的,今天才开始和前端对接,由于这是我第一次做后端接口开发(第一次嘛,问题比较多)所以在此记录分享我的踩坑之旅,以便能更好的理解,应 ...

  9. 六十三:CSRF攻击与防御之系统准备之登录与转账功能

    登录功能 在forms里面添加验证 class LoginForm(Form): email = StringField(validators=[Email(message='邮箱格式错误')]) p ...

  10. visual studio 2019不能在vue文件中直接识别less语法

    试了好多方法,不象vs code那样能直接在template vue文件中就识别less语法下边这种分离的方式是可以的,在项目中也比较实用,将来你代码量大了,样式/脚本也还是要和template代码分 ...