使用parquet-hadoop.jar包解析hive parquet文件时,遇到FIXED_LEN_BYTE_ARRAY转换为Decimal 以及 INT96转换为timestamp问题
时间:2019-11-18
本文章向大家介绍使用parquet-hadoop.jar包解析hive parquet文件时,遇到FIXED_LEN_BYTE_ARRAY转换为Decimal 以及 INT96转换为timestamp问题,主要包括使用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二进制类型,要想得到原来的数据,都需要进行转换,在网上很少能找到相关问题,希望对其他人有所帮助
原文地址:https://www.cnblogs.com/qixing/p/11880262.html
- CentOS6.5菜鸟之旅:VIM插件NERDtree初探
- CentOS6.5菜鸟之旅:安装输入法(小呀小企鹅)
- CSS魔法堂:选择器及其优先级
- 常见的Web实时消息交互方式和SignalR
- 【设计模式】——工厂方法FactoryMethod
- 前端翻译:Activating Browser Modes with Doctype
- JS魔法堂:doctype我们应该了解的基础知识
- CentOS6.5菜鸟之旅:安装Realtek无线网卡驱动
- CentOS6.5菜鸟之旅:U盘安装CentOS64位
- 人工智能创造新型态工作 制造业受冲击
- ASP.NET Core File Providers
- JS魔法堂之实战:纯前端的图片预览
- 域名publica.com近50万交易 买家身份浮出水面
- Vim杂记:Sublime的配色方案
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- java设计一个复制和打印一维数组的工具类
- Moriarty Corp靶场攻略
- Chatterbox(hack the box系列)
- 用云开发实现在线五子棋h5(含源码)
- Duo RDP双因素身份验证防护绕过
- Hackbar 2.3.1插件许可证限制绕过
- Linux系统下安装JDK
- MATLAB借助openai gym环境训练强化学习模型
- java作业篇,闰年,BMI
- 主题hondsome折腾,css修改
- typecho显示网站运行时间
- 从 Dagger 到 Hilt,谷歌为何执着于让我们用依赖注入?
- 为什么非对称加密比对称加密慢?
- 如何优化Nginx的处理性能
- 一键生成前后端代码,Mybatis-Plus代码生成器让我舒服了