Mapreduce中的字符串编码

$$$

Shuffle的执行过程,需要经过多次比较排序。如果对每一个数据的比较都需要先反序列化,对性能影响极大。 RawComparator的作用就不言而喻,能够直接使用序列化后的字节流进行比较,不需要反序列化就能够完成排序功能。

$$$

hadoop使用的是jdk自带编码器和解码器(DataOutputStream和DataInputStream),它有一套规则把字符转化成字节。1个字符可能转化成1个,2个或者3个字节。

字节流开始处用2个字节,写了字节流的有效长度,它的字节流最长是65535 (这个长度是编码后的字节流长度,不是传进行的字符串长度)

在RawComparator读到的,是在这种规则下转换后的字节流,不能够直接使用它来做比较了。。。在 二次排序 里面我用了一种变通的方法解决这个问题。最好的方法是模仿Text的编码和比较器的实现,然后实现自定义key的比较器

在这里主要是解析一下,Why???

DataOutputStream.writeUTF()的源码不长,直接上

    /**
** 把字符串编码为utf字节流,并写进out
**/
static int writeUTF(String str, DataOutput out) throws IOException {
int strlen = str.length();
int utflen = 0;
int c, count = 0; /* 计算编码后的字节流长度 */
for (int i = 0; i < strlen; i++) {
c = str.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) { // ascii字符,1个字符->1个字节
utflen++;
} else if (c > 0x07FF) { // 1个字符->3个字节
utflen += 3;
} else {
utflen += 2; // 1个字符->2个字节
}
} // 编码后的字节流总长度不能超过65535
if (utflen > 65535)
throw new UTFDataFormatException(
"encoded string too long: " + utflen + " bytes"); // 初始化用于编码的缓冲区
byte[] bytearr = null;
if (out instanceof DataOutputStream) {
DataOutputStream dos = (DataOutputStream)out;
if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
dos.bytearr = new byte[(utflen*2) + 2];
bytearr = dos.bytearr;
} else {
bytearr = new byte[utflen+2];
} // 开头的2个字节,写字符串长度 utflen
bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF); // 先写入 [1到7E]的字符, 即ascii字符, 1个字符->1个字节
int i=0;
for (i=0; i<strlen; i++) {
c = str.charAt(i);
if (!((c >= 0x0001) && (c <= 0x007F))) break;
bytearr[count++] = (byte) c;
} for (;i < strlen; i++){
c = str.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) { // ascii字符
bytearr[count++] = (byte) c; } else if (c > 0x07FF) { // 非ascii字符,需要3个字节
bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
} else {
bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F)); // 其余的非ascii字符,需要2个字节
bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
}
}
out.write(bytearr, 0, utflen+2);
return utflen + 2;
}

Mapreduce中的字符串编码的更多相关文章

  1. 使用自己的Python函数处理Protobuf中的字符串编码

    我目前所在的项目是一个老项目,里面的字符串编码有点乱,数据库中有些是GB2312,有些是UTF8:代码中有些是GBK,有些是UTF8,代码中转来转去,经常是不太清楚当前这个字符串是什么编码,由于是老项 ...

  2. 关于python中的字符串编码理解

    python2.x 中中间编码为unicode,一个字符串需要decode为unicode,再encode为其它编码格式(gbk.utf8等) 以gbk转utf8为例: s = "我是字符串 ...

  3. javascript中的字符串编码、字符串方法详解

    js中的字符串是一种类数组,采用UTF-16编码的Unicode字符集,意味字符串的每个字符可用下标方式获取,而每个字符串在内存中都是一个16位值组成的序列.js对字符串的各项操作均是在对16位值进行 ...

  4. Python2和Python3中的字符串编码问题解决

    Python2和Python3在字符串编码上是有明显的区别. 在Python2中,字符串无法完全地支持国际字符集和Unicode编码.为了解决这种限制,Python2对Unicode数据使用了单独的字 ...

  5. python中的字符串编码问题——1.理解编码和解码问题

    理解编码与解码(python2.7):1)编码 是根据一个想要的编码名称,把一个字符串翻译为其原始字节形式.>>> u_str=u'字符串编码aabbbcccddd'>> ...

  6. JavaScript中有对字符串编码的三个函数:escape,encodeURI,encodeURIComponent

    JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decod ...

  7. Python3中转换字符串编码

    在使用subprocess调用Windows命令时,遇到了字符串不显示中文的问题,源码如下:#-*-coding:utf-8-*-__author__ = '$USER' #-*-coding:utf ...

  8. Code::Blocks开发中的字符串编码错误

    刚开始使用Code::Blocks开发Windows中文应用程序的朋友们,如果在代码中使用了中文字符串,编译时可能遇到过Illegal byte sequence或Failure to convert ...

  9. python中的字符串编码问题——4.unicode编解码(以实际工作中遇到的韩文编码为例)

    韩文unicode编解码  问题是这样,工作中遇到有韩文数据出现乱码,说是unicode码. 类似这样: id name 323 52186863 149 63637538 314 65516863 ...

随机推荐

  1. 转载:Windows Phone 8.1 投影我的屏幕使用教程

    原文地址:http://livesino.net/archives/6851.live 更新了软件的下载地址. Windows Phone 8.1 新功能投影我的屏幕(Project My Scree ...

  2. 剑指Offer:面试题16——反转链表(java实现)

    问题描述 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的链表的头结点.链表结点如下: public class ListNode { int val; ListNode next = n ...

  3. SQL必知必会笔记2

    15. 插入数据 1). 数据插入 INSERT 用来将行插入到数据库表中,插入的方式有几种: (1)插入完整的行: INSERT INTO Customers VALUES( '1000000006 ...

  4. git克隆项目到一个非空目录

    这只是记录: 1. 进入非空目录,假设是 /workdir/proj1 2. git clone --no-checkout https://git.oschina.net/NextApp/platf ...

  5. FusionCharts for Flex报错

    1.昨天,我新建了一个Flex项目,并将FusionCharts组件添加进去了,但是Flex应用程序还是报错 具体错误如下: 2.但是,Flex项目已经导入FusionCharts.swc

  6. Guid.NewGuid().ToString()的几种格式

    1.Guid.NewGuid().ToString("N") 结果为:      38bddf48f43c48588e0d78761eaa1ce6 2.Guid.NewGuid() ...

  7. js的replace方法

    今天在项目中发现,js的replace方法,其实只是替换第一个匹配的字符: 比如 backstreetboy.replace('b','B') 得到的结果是Backstreetboy,只是替换了第一个 ...

  8. 8051学习笔记——AD

    AD.C #include<reg52.h> #include <iic.h> #define PCF8591 0x90 //PCF8591 地址 sbit LS138A=P2 ...

  9. 学习记录 java 哈希

    哈希表(Hash Table,又叫散列表),是存储键值对(Key-value)的表,之所以不叫它Map(键值对一起存储一般叫做Map),是因为它下面的特性:它能把关键码(key)映射到表中的一个位置来 ...

  10. 华为OJ平台——统计字符串中的大写字母

    题目描述: 统计字符串中的大写字母的个数 输入: 一行字符串 输出: 字符串中大写字母的个数(当空串时输出0) 思路: 这一题很简单,直接判断字符串中的每一个字符即可,唯一要注意的一点是输入的字符串可 ...