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