Hadoop中Writable类之二
1.ASCII、Unicode、UFT-8
在看Text类型的时候,里面出现了上面三种编码,先看看这三种编码:
ASCII是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO/IEC 646。ASCII是7位字符集,是美国标准信息交换代码的缩写,为美国英语通信所设计。它由128个字符组成,包括大小写字母、数字0-9、标点符号、非打印字符(换行副、制表符等4个)以及控制字符(退格、响铃等)组成。从定义,很明显,单字节编码,现代英语,局限性很大。
由于它是针对英语设计的,当处理带有音标符号的亚洲文字就会出现问题。因此,创建除了一些包含255个字符的由ASCII扩展的字符集。其中有两种比较有名:IBM字符集和ISOLatin-1,但是,仅仅汉语字母表就有80000以上个字符。但是把汉语、日语、越南语的一些相似的字符结合起来,在不同的语言里,使用不同的字符代表不同的字,这样,只用2个字节就可以编码地球上几乎所有的文字。因此UNICODE编码由此创建。
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。和AASCII不同,它共过增加一个 高字节对ISO Latin-1字符集进行扩展,当着写高字节为0时,低字节就是ISO Latin-1字符。
但是,对可以使用ASCII表示的字符使用UNICODE来表示,并不是很高效,因为UNICODE是两个字节组成的,而ASCII是由单字节组成的。UNICODE比ASCII占用大了一倍的空间。为了解决这个问题,就出现了一些中间格式的字符集,他们被称为通用转换格式,即UTF。常见的UTF格式有:UTF-7、UTF-7.5、UTF-8等。
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,又称万国码。由Ken Thompson于1992年创建。现在已经标准化为RFC 3629。UTF-8用1到6个字节编码UNICODE字符。用在网页上可以同一页面显示中文简体繁体及其它语言(如英文,日文,韩文)。UTF-8转换表表示如下:
实际表示ASCII字符的UNICODE字符,将会编码成1个字节。并且UTF-8表示会与ASCII字符表示是一样的。所有其他的UNICODE字符转化成UTF-8将需要至少2个字节。
2.Text类型
<1>Text简介
Text是针对UTF-8序列的Writable类。一般可以认为等价于java.lang.String的Writable。
由于它着重使用标准的UTF-8编码,因此Text类的索引是根据编码后字节序列中的位置实现的。并非字符串中的Unicode字符,也不是Java Char的编码单元。对于ASCII字符串,这三个索引位置的概念是一致的。
<2>String 和 Text区别
上面已经提到了,Text类的索引是根据编码后字节序列中的位置实现的。String的索引是Java Char编码单元实现的。当字符串为ASCII码的时候,也就是全部为7位的单字节的时候,String 和 Text一致!
(1).当字符串为ASCII码(单字节)
Example:
package cn.roboson.writable; import java.io.UnsupportedEncodingException; import org.apache.hadoop.io.Text; /**
* 1.区别Text和String
* 2.首先从ASSCII字符串比较(也就是全部都是7位单字节),
* 3.通过getLength()、getBytes()、charAt()、find()、indexof()、codePointAt()方法来测试
* @author roboson
*
*/
public class WritableText01 { public static void main(String[] args) throws UnsupportedEncodingException {
//Hadoop中全部都是7位单字节(H,a,d,o,o,p)
String str = new String("Hadoop");
Text t = new Text("Hadoop"); //“Hadoop”的长度,也就是所含char编码单元的个数(H,a,d,o,o,p)共6个
System.out.println("String length:"+str.length()); //6 //String的getBytes() 方法返回根据相应编码(此例为utf-8)编码后的字节数,因为Hadoop这个字符串都是单字节的,所以,用utf-8编码,效果同ASCII编码一样,都是6个字节
System.out.println("String getBytes:"+str.getBytes("UTF-8").length); //6 //String的charAt()方法返回的是相应位置的char编码单元
System.out.println("String chartAt:"+str.charAt(0)); //H
System.out.println("String chartAt:"+str.charAt(5)); //p //String的indexOf()方法返回的字符出现的位置
System.out.println("String indexof:"+str.indexOf("H"));
System.out.println("String indexof:"+str.indexOf("p")); //String的codePointAt()方法返回的对应位置的unicode字符集序号
System.out.println("String codePointAt:"+str.codePointAt(0)); //
System.out.println("String codePointAt:"+str.codePointAt(5)); //112 //“Hadoop”的长度,也就是有UTF-8编码后所含有的字节数
System.out.println("Text length:"+t.getLength()); //6 //同indexof()方法相似,返回字节出现的位置
System.out.println("Text find:"+t.find("H")); //
System.out.println("Text find:"+t.find("a")); //1 //Text类的charAt方法也是返回对应的unicode字符集序号
System.out.println("Text char:"+t.charAt(0)); //
System.out.println("Text char:"+t.charAt(1)); //
}
}
运行结果:
(2).当字符串为多个字节
一旦使用多个字节来编码时,Text和String之间区别就很明显了
Unicode code point | U+0041 | U+00DF | U+6771 | U+10400 |
UTF-8 code units | 41 | c3 9f | e6 9d b1 | fo 90 90 80 |
Java representation | \u0041 | \u00DF | \u6771 | \uD801 \uDC00 |
第一行表示unicode字符集中的序号(也是以16进制表示),第二行表示的是采用utf-8编码的情况,第三行表示的是用utf-16编码的情况,可以看到,第四个字符在utf-16编码下也占用4个字节(两个char单元,每个char单元是两字字节)
分析:
Text t = new Text("\u0041\u00DF\u6771\uD801\uDC00");
Text中的长度是由编码后字节的个数所决定的!那么,字节的个数是如何算的呢?在上文的UTF-8转换表图中有说明:
如下图,是t的字节数的实现,通过其二进制的位数,然后,同UTF-8转换表对比,从而得出其字节数!
unicode | 二进制 | 位数 | 字节数 |
U+0041 | 1000001 | 7 | 1 |
U+00DF | 11011111 | 8 | 2 |
U+6771 | 110011101110001 | 15 | 3 |
U+10400 | 10000010000000000 | 17 | 4 |
t的长度:1+2+3+4=10;
可以通过下面的例子来验证:
Example:
package cn.roboson.writable; import java.io.UnsupportedEncodingException; import org.apache.hadoop.io.Text; public class WtitableText {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "\u0041\u00DF\u6771\uD801\uDC00"; Text text = new Text("\u0041\u00DF\u6771\uD801\uDC00"); System.out.println(str.length()); // System.out.println(str.getBytes("UTF-8").length); //
String str1="\u0041";
System.out.println(str1.getBytes("UTF-8").length); //
String str2="\u00DF";
System.out.println(str2.getBytes("UTF-8").length); //
String str3="\u6771";
System.out.println(str3.getBytes("UTF-8").length); // String str4="\uD801\uDC00";
System.out.println(str4.getBytes("UTF-8").length); // System.out.println(str.indexOf("\u0041")); //
System.out.println(str.indexOf("\u00DF")); //
System.out.println(str.indexOf("\u6771")); //
System.out.println(str.indexOf("\uD801\uDC00")); // System.out.println(str.charAt(0)=='\u0041'); //true
System.out.println(str.charAt(1)=='\u00DF'); //true
System.out.println(str.charAt(2)=='\u6771'); //true
System.out.println(str.charAt(3)=='\uD801'); //true
System.out.println(str.charAt(4)=='\uDC00'); //true System.out.println(str.codePointAt(0)); //
System.out.println(str.codePointAt(1)); //
System.out.println(str.codePointAt(2)); //
System.out.println(str.codePointAt(3)); // System.out.println(text.getLength()); //
System.out.println(text.find("\u0041")); //
System.out.println(text.find("\u00DF")); //
System.out.println(text.find("\u6771")); //
System.out.println(text.find("\uD801\uDC00")); // System.out.println(text.charAt(0)); //
System.out.println(text.charAt(1)); //
System.out.println(text.charAt(3)); //
System.out.println(text.charAt(6)); //
}
}
运行结果:
3.Text类型的迭代
通过上面,也知道,通过字节量进行位置索引来实现对Text类Unicode字符的迭代是非常复杂的,因为字节数变化很大(1~6),你不能简单地通过增加位置的索引值来实现。
迭代的实现:
将Text对象转换为Java.nio.ByteBuffer对象,然后利用缓冲去对Text对象反复调用bytesToCodePoint()静态方法。该方法能头获取下一代码的位置,并返回相应的int值,最后更新缓冲区中的位置。通过bytesToCodePoint()方法可以检测出字符串的末尾,并返回-1.
Example:遍历Text对象中的字符
package cn.roboson.writable; import java.nio.ByteBuffer; import org.apache.hadoop.io.Text; public class WritableText03 { public static void main(String[] args) {
Text t = new Text("\u0041\u00DF\u6771\uD801\uDC00");
ByteBuffer buf = ByteBuffer.wrap(t.getBytes(),0,t.getLength());
int cp;
while(buf.hasRemaining() && (cp = Text.bytesToCodePoint(buf))!=-1){
//以十六进制的无符号整数形式返回一个整数参数的字符串表示形式。
System.out.println(Integer.toHexString(cp));
}
}
}
运行结果:
4.Text类型的易变性
与String相比,Text的另一个区别在于它是可变的。可以通过调用其中一个set()方法来重用Text实例。
在某些情况下,getBytes()方法返回的字节数组可能比getLength()函数返回的长度更长,因此,在调用getBytes()之前,始终调用getLength()方法,因为,可能由此知道字节数组的中有多少是有效的。至于原因,还没弄明白
package cn.roboson.writable; import org.apache.hadoop.io.Text; public class WritableText04 { public static void main(String[] args) {
Text t = new Text("Hadoop");
System.out.println("Hadoop的长度:"+t.getLength());
System.out.println("Hadoop的字节数组:"+t.getBytes().length); t.set(new Text("robo"));
System.out.println("robo的长度:"+t.getLength());
System.out.println("robo的字节数组:"+t.getBytes().length);
}
}
运行结果:
set(String str);
set(Text text);这两种的效果又不一样。
Example:
package cn.roboson.writable; import org.apache.hadoop.io.Text; public class WritableText04 { public static void main(String[] args) {
Text t = new Text("Hadoop");
System.out.println("Hadoop的长度:"+t.getLength());
System.out.println("Hadoop的字节数组:"+t.getBytes().length); t.set("robo");
System.out.println("robo的长度:"+t.getLength());
System.out.println("robo的字节数组:"+t.getBytes().length);
}
}
运行结果:
参考:
http://www.cnblogs.com/yuhan-TB/p/3752725.html
《Hadoop权威指南》
Hadoop中Writable类之二的更多相关文章
- Hadoop中Writable类之四
1.定制Writable类型 Hadoop中有一套Writable实现,例如:IntWritable.Text等,但是,有时候可能并不能满足自己的需求,这个时候,就需要自己定制Writable类型. ...
- Hadoop中Writable类之三
1.BytesWritable <1>定义 ByteWritable是对二进制数据组的封装.它的序列化格式为一个用于指定后面数据字节数的整数域(4个字节),后跟字节本身. 举个例子,假如有 ...
- Hadoop中Writable类
1.Writable简单介绍 在前面的博客中,经常出现IntWritable,ByteWritable.....光从字面上,就可以看出,给人的感觉是基本数据类型 和 序列化!在Hadoop中自带的or ...
- python中的类(二)
python中的类(二) 六.类的成员 字段:普通字段,静态字段 eg: class Province(): country=’中国’ #静态字段,保存在类中,执行时可以通过类或对象访问 def __ ...
- hadoop中Text类 与 java中String类的区别
hadoop 中 的Text类与java中的String类感觉上用法是相似的,但两者在编码格式和访问方式上还是有些差别的,要说明这个问题,首先得了解几个概念: 字符集: 是一个系统支持的所有抽象字符的 ...
- 谈谈Python中元类Metaclass(二):ORM实践
什么是ORM? ORM的英文全称是“Object Relational Mapping”,即对象-关系映射,从字面上直接理解,就是把“关系”给“对象”化. 对应到数据库,我们知道关系数据库(例如Mys ...
- Java并发包中常用类小结(二)
6.ThredPoolExecutor ThredPoolExecutor是基于命令模式下的一个典型的线程池的实现,主要通过一些策略实现一个典型的线程池,目前已知的策略有ThreadPoolExecu ...
- hadoop中典型Writable类详解
本文地址:http://www.cnblogs.com/archimedes/p/hadoop-writable.html,转载请注明源地址. Hadoop将很多Writable类归入org.apac ...
- hadoop中实现定制Writable类
Hadoop中有一套Writable实现可以满足大部分需求,但是在有些情况下,我们需要根据自己的需要构造一个新的实现,有了定制的Writable,我们就可以完全控制二进制表示和排序顺序. 为了演示如何 ...
随机推荐
- CentOS 6.5系统安装编译安装MySQL 5.6详细过程
点评:CentOS 6.5下通过yum安装的MySQL是5.1版的,比较老,那我们就通过源代码安装高版本的MySQL5.6.14.一:卸载旧版本使用下面的命令检查是否安装有MySQL Server r ...
- tomcat自启动脚本
1.#cd /etc/rc.d/init.d2.#vi tomcat3.把下面的代码保存为tomcat文件,并让它成为可执行文件 chmod 755 tomcat. #!/bin/sh # # /et ...
- 基于ffmpeg静态库的应用开发
最近几天在试着做基本ffmpeg静态库的开发,只有main中包含了avdevice_register_all 或avfilter_register_all,编译就通不过,undefined refre ...
- settimeout()在IE8下参数无效问题解决方法
遇到这个问题,setTimeout(Scroll(),3000); 这种写法在IE8 下 不能够执行,提示参数无效, setTimeout(function(){Scroll()},3000);这种方 ...
- 4.Appium实现自动化安装apk
一.代码如下所示: from appium import webdriver import os apk_path = os.path.abspath(os.path.join(os.path.dir ...
- 【python】python实例集<一>
#打开一个记事本 import os os.startfile('notepad.exe') #当前文件的根目录 import os print os.path.join(os.path.dirnam ...
- word文档批量合并工具
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. ; #Warn ; En ...
- Boost C++ 库 中文教程(全)
Boost C++ 库 目录 第 1 章 简介 第 2 章 智能指针 第 3 章 函数对象 第 4 章 事件处理 第 5 章 字符串处理 第 6 章 多线程 第 7 章 异步输入输出 第 8 章 进程 ...
- appium -ios 真机连接 环境搭建
补充点一: 安装ios-deploynpm install -g ios-deploy 安装不了报错.! 后来找了找,发现sudo npm install -g ios-deploy --unsafe ...
- POJ 2395 Out of Hay(求最小生成树的最长边+kruskal)
Out of Hay Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 18472 Accepted: 7318 Descr ...