在使用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. 应用程序无法正常启动(0xc000007b)请单击确定关闭程序

    1.问题 在win10 VS2105 环境下面开发了一个调用get接口获取数据然后写入pg数据库的程序,在自己电脑上运行正常.复制到win7环境下运行,单击出现如下图所示的提示框. 2.原因分析 出现 ...

  2. error while loading shared libraries: libXXXX.so: cannot open shared object file: No such file or directory

    出现这个问题的原因是运行程序缺少依赖库,或者运行程序的依赖库缺少依赖库,可能你的本地目录下面就有这个库文件,但是linux搜索路劲不会从当前路径下去搜索:这种情况可能出现在切换环境上,可能你在一个li ...

  3. 使用Python进行层次聚类

    使用 scipy.cluster.hierarchy.linkage进行层次聚类 from scipy.cluster.hierarchy import dendrogram, linkage,fcl ...

  4. C++:#include和using namespace

    https://blog.csdn.net/u013719339/article/details/80221899

  5. 打开下载CA root 证书的链接失败

    下载CA root 证书 http://adip/certsrv server error or refuse to connect 这是由于AD上没有安装Active Directory Certi ...

  6. dpkg -l 命令返回数值

    ubuntu命令: dpkg -l 每条记录对应一个软件包,每条记录的第一,二,三个字符是软件包的状态标识,后边依此时软件包名称,版本号,和简述:   第一个字符为,期望值:包括如下状态: u 状态未 ...

  7. vmware安装centos虚拟机,没有ip地址

    如果centos没有ip地址,就不能通过xshell等工具进行连接,且在上面部署的项目,外部也不能正常访问 两种方式可以解决 第一种,在安装的时候,在INSTALLATION SUMMARY界面的SY ...

  8. 淘宝TAE平台定时任务包的部署步骤

    淘宝TAE平台定时任务包的部署: 第一步:首先把自己的任务打包成一个jar包.使用maven打包的命令为:mvn clean install 第二步:把任务jar包依赖的jar包全部导出来.使用mav ...

  9. 菜鸟的周末_Python试水

    搭建开发环境 下载安装包,打开官网,选择最新Windows Installer版本下载. 运行安装包,勾选Add Python 3.8 to Path,选择Install Now,等待安装完成,直接关 ...

  10. layui弹出层处理(获取、操作弹出层数据等)

    要点: 字符串被渲染为弹窗层之后,回自动转换为DOM,可以使用jq进行各种操作 <!DOCTYPE html> <html> <head> <meta cha ...