hadoop 中
的Text类与java中的String类感觉上用法是相似的,但两者在编码格式和访问方式上还是有些差别的,要说明这个问题,首先得了解几个概念;
字符集:
是一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。例如
unicode就是一个字符集,它的目标是涵盖世界上所有国家的文字和符号;
字符编码:是一套法则,使用该法则能够对自然语言的字符的一个集合(如字母表或音节表),与其他东西的一个集合(如号码或电脉冲)进行配对。即在符号集合与数字系统之间建立对应关系,它是信息处理的一项基本技术。通常人们用符号集合(一般情况下就是文字)来表达信息。而以计算机为基础的信息处理系统则是利用元件(硬件)不同状态的组合来存储和处理信息的。元件不同状态的组合能代表数字系统的数字,因此字符编码就是将符号转换为计算机可以接受的数字系统的数,称为数字代码。
字符编码与字符集通常是一一对应的关系,例如utf-8,utf-16,utf-32都是unicode的不同编码格式;
utf-8: 将unicode字符集分成1~4个字节的形式表示
utf-16:
将unicode中编号从1到65536的字符都用两个字节表示(因为前65536个被认为是常用字符),大于65536的字符通过变换的方法变成4个字节来存储;
utf-8 与 utf-16具体的编码变换方法,大家感兴趣的话可以从网上搜索来看;
Hadoop中的Text类为了与外界更好的交互,采用的是utf-8的编码,而java的char,String,StringBuffer则默认使用的是utf-16编码;两者在使用和访问的时候其实是有一些差别的。
这里借用了网上一篇博客中的例子
: http://blog.csdn.net/lastsweetop/article/details/9249411
来说明Text类与String类在访问上的区别
第一个行表示unicode字符集中的序号(也是以16进制表示),第二行表示的是采用utf-8编码的情况,第三行表示的是用utf-16编码的情况,可以看到,第四个字符在utf-16编码下也占用4个字节(两个char单元,每个char单元是两字字节);
代码如下,下面会分别解释结果中每一行的意思;
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);
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‘);
System.out.println(str.charAt(1)==‘\u00DF‘);
System.out.println(str.charAt(2)==‘\u6771‘);
System.out.println(str.charAt(3)==‘\uD801‘);
System.out.println(str.charAt(4)==‘\uDC00‘);
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));
5 //String
中的getLength表示的是字符串中char单元的个数,如果String中包含4个字节(两个char单元)表示的字符,像上文中的第四个字符,getLength也是统计的是char
的数量,此时getLength的结果与实际的字符数是不同的。
10 //getBytes()
方法返回根据相应编码(此例为utf-8)编码后的字节数;四个字符按utf-8编码后的字节数分别为1、2、3、4,所以总的字节数是10
0 //String
的indexOf方法返回的字符出现的位置;
1
2
3
true
//String的charAt方法,返回的是相应位置的char编码单元
true
true
true
true
65
//String类的codePointAt()方法返回的是对应位置的unicode字符集序号,即上文u+0041的十进制表示;
223
//
26481
66560
//这里要特别强调一下,由于第四个字符占据了两个char单元,codePointAt()方法会进行相应的判断,如果发现之后一位的char单元与当前位置的char单元是从属于一个
unicode字符的话,就将两者和在一起;如果不是的话,就单独输出当前的char单元;
10 //Text
类的getLength方法返回的是utf-8编码之后的字节数
0
//Text类的find方法也是按照字节数的偏移位置来的
1
3
6
65
//Text类的charAt方法也是返回对应的unicode字符集序号;
223
26481
66560
//如果这一句换成 charAt(5) 那么返回的是 -1
由于Text的特点决定了:对Text的遍历会麻烦一些,需要变成bytes后通过bytesToCodePoint()方法进行访问;
ByteBuffer buffer = ByteBuffer.wrap(text.getBytes(), 0, text.getLength());
int cp;
while (buffer.hasRemaining() && (cp =
Text.bytesToCodePoint(buffer)) != -1) {
System.out.println(Integer.toHexString(cp) + "haha");
}
输出结果为:
41
df
6771
10400
hadoop中Text类 与 java中String类的区别,布布扣,bubuko.com