Hadoop中VIntWritable编码方式解析

2023-05-16

最近因为实验室的云计算项目,开始学习Hadoop,有时间就记录一下自己在学习过程中的一些小收获吧。


《Hadoop权威指南》在序列化这一节有个例子程序,叫做TextPair,代码略长,就不贴上来了,它implements了WritableComparable<TextPair>,将两个Text对象打包到一起。TextPair以静态内部类的形式实现了WritableComparator,这样,不从数据流中deserialize出对象也可以对TextPair进行比较了。实现的这个Comparator中的compare方法如下:

 

Java代码   收藏代码
  1. @Override  
  2.     public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {  
  3.   
  4.         try {  
  5.         int firstL1 = WritableUtils.decodeVIntSize(b1[s1])  
  6.             + readVInt(b1, s1);  
  7.         int firstL2 = WritableUtils.decodeVIntSize(b2[s2])  
  8.             + readVInt(b2, s2);  
  9.         int cmp = TEXT_COMPARATOR.compare(b1, s1, firstL1, b2, s2,  
  10.             firstL2);  
  11.         if (cmp != 0) {  
  12.             return cmp;  
  13.         }  
  14.         return TEXT_COMPARATOR.compare(b1, s1 + firstL1, l1 - firstL1,  
  15.             b2, s2 + firstL2, l2 - firstL2);  
  16.         } catch (IOException e) {  
  17.         throw new IllegalArgumentException(e);  
  18.         }  
  19.     }  
 


  中间有两行代码比较有意思,int firstL1 = WritableUtils.decodeVIntSize(b1[s1])+ readVInt(b1, s1); 以及它之后的那一行类似的。第一个方法,decodeVIntSize,先看代码:

 

Java代码   收藏代码
  1. public static int decodeVIntSize(byte value) {  
  2.     if (value >= -112) {  
  3.       return 1;  
  4.     } else if (value < -120) {  
  5.       return -119 - value;  
  6.     }  
  7.     return -111 - value;  
  8.   }  
 


  这个方法的功能是判断VInt的长度。这里还是稍微记一下VInt和Text,以免将来忘记。


 写道
Text使用一个采用可变长度编码方案的int在字符串编码中存储字节数。


  在decodeVIntSize方法中,现在只能是看到做了分类处理,但是具体是怎么分类还不太清楚。接着是readVInt这个方法,它是WritableComparator中的静态工具方法,我在WritableUtils工具类中也看到了类似的方法,这个在后边会贴出来。

 

Java代码   收藏代码
  1. public static int readVInt(byte[] bytes, int start) throws IOException {  
  2.     return (int) readVLong(bytes, start);  
  3.   }  
  4.   
  5. public static long readVLong(byte[] bytes, int start) throws IOException {  
  6.     int len = bytes[start];  
  7.     if (len >= -112) {  
  8.       return len;           //1  
  9.     }  
  10.     boolean isNegative = (len < -120);    //2  
  11.     len = isNegative ? -(len + 120) : -(len + 112);   //3  
  12.     if (start+1+len>bytes.length)    //4  
  13.       throw new IOException(  
  14.                             "Not enough number of bytes for a zero-compressed integer");  
  15.     long i = 0;  
  16.     for (int idx = 0; idx < len; idx++) {    //5  
  17.       i = i << 8;  
  18.       i = i | (bytes[start+1+idx] & 0xFF);  
  19.     }  
  20.     return (isNegative ? (i ^ -1L) : i);     //6  
  21.   }  
 


  readVInt引用了readVLong方法,readVLong从字节序列中尝试读取出一个采用变长编码方案的Long。因此,关键就在这个readVLong中了。

在标号1的地方,如果第一个byte>=-112,就将这个byte返回,亦即代表这就是我们想要的那个数,可以再结合 decodeVIntSize这个方法,可以确定,在VInt或VLong中,一个字节能表示的数是从0~127, -112~-1的,当数字小于了-112就会做特殊处理了,这就是开始用两个字节来存放。

往下看,在标号2的地方,又做了判断。要注意到的是,代码走到这里,表示要去的那个Int或Long已经不是用一个byte来表示的了,也就是说,第一个byte是用作长度标识了,但是从标号2这里又可以看出,第一个byte还可以用来判断这个数字是正数还是负数,从标号三可以看出,正负数的长度存储是不同的,原因从后面的代码可以看出。另外,这里分别为正数和负数做了最大8个byte长度的限制。VLongWritable的最大长度就是9,这里减一即是8.

在到达标号4时候,这个数字的长度已经计算出来了,剩下的就是解码出数字了,但是,如果解码出数字所需的byte数目超出了这个bytes数组的boundary,就只能抛出异常了。

从标号5开始对剩下的数据进行解码,对java的byte处理有点了解的都应该看得懂,只做一个对自己的提醒,使用bytes[start+1+idx] & 0xFF是为了确保获得正确的byte值,以防java帮你自动转换。如果你的byte的most significant bit是1,也就是说明这个byte是表示的负数,如果将这个负数与一个Long进行位的或操作,这个byte的所有高于第9位的所有位都会被填充上1,这可不是我们想要的。

标号6,之前做的判断这里用到了,如果是负数,就对它取-1,也就是11111111...(64个1,-1的二进制表示),的反,这么做的原因是在写入这个VInt或VLong的时候做了相反的操作,具体为什么这样我也高步太懂,但是这么做所有的数据byte(就是除了第一个byte)的most significant bit都是0.


以上两个方法 decodeVIntSize + readVInt 就完美地解析出了一个完整Text的长度。


在WritableComparator中并没有写VIntWritable或VLongWritable的方法,这时候找到VIntWritable。

 

Java代码   收藏代码
  1. public void readFields(DataInput in) throws IOException {  
  2.     value = WritableUtils.readVInt(in);  
  3.   }  
  4.   
  5.   public void write(DataOutput out) throws IOException {  
  6.     WritableUtils.writeVInt(out, value);  
  7.   }  
 


  嗯,大哥来了,WritableUtils,代码参上。同样,writeVInt引用了writeVLong

Java代码   收藏代码
  1. public static void writeVLong(DataOutput stream, long i) throws IOException {      
  2.    if (i >= -112 && i <= 127) {  
  3.       stream.writeByte((byte)i);  
  4.       return;  
  5.     }  
  6.         
  7.     int len = -112;  
  8.     if (i < 0) {  
  9.       i ^= -1L; // take one's complement'  
  10.       len = -120;  
  11.     }  
  12.         
  13.     long tmp = i;  
  14.     while (tmp != 0) {  
  15.       tmp = tmp >> 8;  
  16.       len--;  
  17.     }  
  18.         
  19.     stream.writeByte((byte)len);  
  20.         
  21.     len = (len < -120) ? -(len + 120) : -(len + 112);  
  22.         
  23.     for (int idx = len; idx != 0; idx--) {  
  24.       int shiftbits = (idx - 1) * 8;  
  25.       long mask = 0xFFL << shiftbits;  
  26.       stream.writeByte((byte)((i & mask) >> shiftbits));  
  27.     }  
  28.   }  
 


  如果已经看到这里,我想也没有太多好说的了,先判断可不可以用一个byte表示,然后分为正负数处理,之后再计算长度,最后将数字编码成byte写入流。其实我写到这里才觉得,如果先找到write方法,什么都一目了然了,但是都写了这么多了,哎。。。就将就这样吧。

最后把大哥的readVLong也贴出来,这个方法是直接从stream中而不是从byte数组中读取,所以略有不同,但是思想还是一样的。

 

Java代码   收藏代码
  1. public static long readVLong(DataInput stream) throws IOException {  
  2.     byte firstByte = stream.readByte();  
  3.     int len = decodeVIntSize(firstByte);    //这个函数应该还是比较熟悉了吧  
  4.     if (len == 1) {  
  5.       return firstByte;  
  6.     }  
  7.     long i = 0;  
  8.     for (int idx = 0; idx < len-1; idx++) {  
  9.       byte b = stream.readByte();  
  10.       i = i << 8;  
  11.       i = i | (b & 0xFF);  
  12.     }  
  13.     return (isNegativeVInt(firstByte) ? (i ^ -1L) : i);  
  14.   }  
 

 

内容比较乱,东西也比较简单,主要目的还是给自己理清一下思路,方便以后回头能直接了然于心。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Hadoop中VIntWritable编码方式解析 的相关文章

  • 原创:自己写的端口数据转发工具pf (port forwarding)

    看了 子清行 朋友博客里的一篇文章 xff0c 讲述了一个叫 DuplexPipe 的小工具的实现 最开始没怎么懂意思 xff0c 看了他公开的源代码 xff0c 是用java写的 xff0c 一个jar包 可惜我不太会java 因此没法看
  • 又一次被linux的工具震惊了

    前一篇博客还写了自己写的端口转发工具 xff0c 今天偶然在网上看到讲命名管道和netcat配合的用法 xff0c 被彻底雷倒了 原来以为netcat做不到 xff0c 原来是自己想不到 xff0c 而不是netcat做不到 方法如下 xf
  • Ubuntu桌面旋转xrandr

    项目实行过程中 xff0c 设备安装为竖屏模式 xff0c 分辨率由19201080变为10801920 xff1b 最简单实现 xff0c 将桌面系统显示旋转 xff1a xff08 终端命令 xff09 xrandr o left 向左
  • VR应用在直播领域上的实践与探索

    声明 xff1a 本文来自 七牛云主办的架构师实践日 泛娱乐 43 直播技术最佳实践 的演讲内容整理 PPT 速记和现场演讲视频等参见 七牛架构师实践日 官网 嘉宾 xff1a 孙其瑞 xff0c 得图网络CTO 责编 xff1a 钱曙光
  • ubuntu(14):ubuntu16编译move_base报错与解决

    目录 1 Could NOT find OpenVDB missing OPENVDB LOCATION 2 Could not find a package configuration file provided by 34 costma
  • 在CSDN发布博客怎么改变代码块颜色

    第一步 CSDN首页 xff0c 最右侧点击创作中心 第二步 左侧导航栏滑到最下面 xff0c 点击博客设置 第三步 找到代码片样式 xff0c 简单吧 xff08 又水了一篇 xff09
  • 裸机驱动与Linux设备驱动的区别

    裸机驱动一般针对没有操作系统支持的层面 不用考虑操作系统对它的调用 Linux驱动是在裸机驱动基础上 按照一定的规范来实现 虽然实现的都是同一个东西 不过你发现在 Linux驱动 搀杂 了许多维护信息 总之 xff0c Linux设备驱动就
  • 使用2020版IDEA创建Servlet

    使用2020版IDEA创建一个完整的Web项目的整个过程分为四步 第一步 创建一个普通的Java项目 1 打开IDEA xff0c 选择菜单File gt New gt Project 2 选择Java xff0c 以及自己的JDK xff
  • Apache IoTDB 系列教程-5:常见问题汇总(1)

    在过去的一段时间 xff0c 收集了不少大家在使用过程中反馈的问题 xff0c 今天把一些常见问题列出来 xff0c 给更多人提供参考 开了个交流群二维码 xff0c 可以扫码进群 正文 1974 字 xff0c 预计阅读时间 5 分钟 常
  • Apache IoTDB 系列教程-6:性能优化(0.8-0.10)

    今天的内容包括建模优化 读写性能优化 xff0c 会涉及一些简单的原理介绍 主要面向 0 8 0 10 版本 正文 3754 字 xff0c 预计阅读时间 10 分钟 建模指南 关于存储组 现在每个存储组是一个相对独立的引擎 xff0c 而
  • Apache IoTDB 系列教程-8:文件同步工具

    在官网用户手册的系统工具 xff08 System Tools xff09 一栏 xff0c 有一个同步工具 xff08 Sync Tool xff09 xff0c 有很多人问这个东西怎么用 xff0c 延迟是多少 xff0c 今天就介绍一
  • Apache IoTDB failed to start RPC ServerService, because Could not create ServerSocket on address

    原因 一般是端口占用 xff0c 可以 jps 检查是不是已经启动了一个 IoTDB
  • Apache IoTDB Query is time out (-1ms)

    现象 查询超时 xff0c 服务器出现一下日志 2022 01 05 15 57 05 724 pool 12 IoTDB query time manager 1 WARN o a i d q c QueryTimeManager 71
  • 解读事务的ACID!

    事务的ACID特性大学数据库课程基本都学过 xff0c 但是学完也就大概知道是干嘛的 xff0c 后来也没仔细想这个东西了 xff0c 后来接触了NoSQL系统的一致性 xff0c 于是重新学习 ACID xff0c 发现还有很多误区 今天
  • 欢迎加入 Apache IoTDB !

    官方网站 xff1a http iotdb apache org zh IoTDB 是清华自研时间序列数据库 xff0c 2014年项目启动 xff0c 2018年11月18号 IoTDB 正式进入 Apache 孵化器 xff0c 成为中
  • Xavier(2):Xavier NX刷机步骤及报错解决

    1 下载和安装NVIDIA SDK Manager 官方网站 xff1a https developer nvidia com embedded jetpac 选择sdk manager xff0c sdk manager版本没有要求 安装
  • 模型评估与优化1--基本概念与最优化问题

    模型评估与优化1 基本概念与最优化问题 首先先看一下基本术语和概念 1 数据集的划分 xff08 1 xff09 数据集 dataset xff1a 在机器学习任务中使用的一组数据 数据集中每一个数据称为一个样本 反映样本在某方面的表现或性
  • windows中vscode编译运行c++程序

    1 vscode 安装 c 43 43 扩展 在vscode中创建一个后缀为 01 cpp 的程序 xff0c 程序文件如下 xff0c vscode会自动提示安装 c 43 43 扩展 xff0c 点击进行安装 01 cpp includ
  • leetcode 刷题指南 & 刷题顺序

    1 刷题方法 amp 顺序 xff1a 按类型刷 xff0c 这样能总结出每种类型题目的规律 优先树 链表 二分查找 DFS BFS 动态规划数目 xff1a 常见类型刷10道 43 顺序 xff1a 先做2 4道简单题 xff0c 然后做
  • 北邮计算机学院2017届复试经验分享

    北邮计算机学院2017届复试经验分享 建议初试完了再来担心复试 xff0c 有看复试经验的时间还不如多做两道数学题 xff01 导师 xff1a 了解导师的情况 xff0c 最差也不要找一个人不好的老师 xff0c 其次尽量选自己喜欢的方向

随机推荐

  • STM32 Cube BMP180 获取温度、气压、海拔

    一 介绍 BMP180中内置有E2PROM xff0c 所以要获取数据 xff0c 就要使用I2C读写E2PROM来实现获取数据 xff01 BMP180的整个流程 xff1a 1 首先要初始化 xff0c 读取几个E2PROM地址上的值共
  • int 类型究竟多少字节?

    今天发现NEON技术中 int类型的字节数是2 xff0c 感觉很奇怪 xff0c 最早写51单片机时也是2 xff0c 后来到了观念转变成了4 xff0c 现在有遇到了2 一 转自 http www tuicool com article
  • python实现K均值聚类算法

    之前做大作业的时候本来想用聚类法给点集分类的 xff0c 但是太复杂了 xff0c 于是最后没有采用这个方案 现在把之前做的一些工作整理出来写个小博客 K means聚类法原理 xff1a 聚类是一个将数据集中在某些方面相似的数据成员进行分
  • 复合型自适应步长的Gauss型求积(附代码)

    复合型自适应步长的Gauss型求积 先前在做数值分析实验时 xff0c 把高斯型求积公式和复合型 自适应步长的求积融合到了一起 xff0c 但是后来发现题目没有这个要求 现在就把这个思路分享一下 上题目 xff1a 实验目的 xff1a 学
  • pid摄像头循迹(opencv和openmv)

    pid摄像头循迹 xff08 opencv和openmv xff09 用摄像头进行循迹的方法参考硬件选型方面软件思路一 图像预处理 xff1a 代码部分二 线性拟合opencv线性拟合 xff1a 实际在树莓派上运行时 xff0c 帧率也比
  • 通过云端自动生成openmv的神经网络模型,进行目标检测

    通过云端自动生成openmv的神经网络模型 xff0c 进行目标检测 OpenMV训练神经网络模型 xff08 目标识别 xff09 一 准备材料 xff1a 二 软件下载三 准备数据集 xff1a 四 数据集的上传与训练 OpenMV训练
  • opencv学习(9):cv::Scalar、cv::Mat::zeros

    1 cv Scalar cv Scalar是opencv的一个结构体 xff0c 其定义如下 xff1a xff08 c 43 43 中的结构体如下 xff0c 可以存放1 4个数值 xff09 various constructors S
  • 德国大陆ARS408系列毫米波雷达数据解析

    本人已完成对该型号系列毫米波雷达的解析工作 xff0c 有需求请私信联系
  • nmap使用详解

    nmap介绍 nmap xff08 Network Mapper xff09 是一款开源免费的针对大型网络的端口扫描工具 xff0c nmap可以检测目标主机是否在线 主机端口开放情况 检测主机运行的服务类型及版本信息 检测操作系统与设备类
  • OLED屏幕花屏的原因(I2C+DMA)

    OLED屏幕在通电后花屏 xff0c 呈雪花状 在网上查询原因 xff0c 开始了尝试 xff1a 1 可能是由于杜邦线的问题 xff0c 可能接触不良导致 xff0c 但更换了杜邦线依然花屏 2 可能是OLED屏幕问题 因为经常在工作 x
  • 竞赛保研(自动化专业)

    一 感谢 从大三的五月份一直到9 28号推免结束 xff0c 最终也是保研到了梦校 xff0c 还好我坚持到了最后一刻 感谢父母 xff0c 感谢远方的她 xff0c 感谢老师 xff0c 感谢实验室的平台 xff0c 也要感谢每一位一起拼
  • 随机森林的简单学习记录

    随机森林小记 这里采用的随机森林的库选择sklearn库 1 首先是导入数据 xff1a path span class token operator 61 span span class token string 34 D Epilept
  • Linux的c++环境配置与cmake的使用

    Ubuntu18 04安装 虚拟机安装 虚拟机软件版本 xff1a VMware Workstation 16 Pro 版本号 xff1a Ubuntu18 04 安装参考 xff1a http t csdn cn P71XR 虚拟机分辨率
  • 用KDevelop来编辑与编译ROS文件

    新建一个ROS工程 xff1a 首先在工作目录下打开终端 xff0c 创建一个src目录 xff0c 放置源代码 xff08 系统要求 xff09 xff0c 并将当前目录切换到src目录中 xff1a mkdir src cd src s
  • 自制三维激光扫描建模

    看图片就是我做的东西 xff0c 很炫酷是不是 好吧 xff0c 开玩笑 xff0c 这是电影普罗米修斯的截图 当初看这个电影的时候就感觉这东西好眩酷 xff0c 我能不能做出来 最近借着帮做毕业设计的机会我也做了一个 就是这个丑丑的东西啦
  • ICE C++ Hello World

    ICE C 43 43 Hello World实例教程 1 概述 本文演示了如何编写一个最简单的C 43 43 ICE Internet Communications Engine 应用程序 xff0c 包括必要环境的安装 该应用程序包含客
  • 华为工作的感悟

    参考 xff1a http www openlab net cn forums thread 1002986 1 p10035795 北邮北 xff0c 清华硕 xff0c 一年两个月的华为生活总结 xff0c 算了 xff0c 贴出来了
  • MRCP 媒体资源控制协议

    媒体资源控制协议 xff08 Media Resource Control Protocol MRCP xff09 是一种通讯协议 xff0c 用于语音服务器向客户端提供各种语音服务 如语音识别和语音合成 MRCP并不定义会话连接 xff0
  • matlab(1):使用matlab处理excel数据进行画图

    目录 0 说明 1 直接使用xlsread读取出错 2 解决办法 3 绘图 0 说明 Excel数据示例 xff08 number filter radius 0 8 3 csv xff09 xff0c 一共99行数据 xff08 4列 x
  • Hadoop中VIntWritable编码方式解析

    最近因为实验室的云计算项目 xff0c 开始学习Hadoop xff0c 有时间就记录一下自己在学习过程中的一些小收获吧 Hadoop权威指南 在序列化这一节有个例子程序 xff0c 叫做TextPair xff0c 代码略长 xff0c