MapReducer中文编码

如果输入文件有中文,输出文件可能会出现乱码。乱码问题的话一般都是编解码错误。
本文的最后有一篇参考文档,那篇文档已经解决了问题了,但是,可是自己是小白,那篇文档没做解释的话,有的我理解不了,所以就把那篇文章解释了一遍。基础好的可以直接看那篇文章。

编码的问题

首先看一下这段代码

String s = "中国";
Text t1 = new Text();
Text t2 = new Text();

t1.set(s.getBytes());
t2.set(s);


############  s   #####################
System.out.println(new String(s.toString()));
//结果是:中国

test01.printByte(s.getBytes());
//结果是:-42   -48 -71 -6

############   t1  ##################
System.out.println(new String(t1.toString()));
//结果是:?й?

test01.printByte(t1.getBytes());  // 打印数组的方法
//结果是:-42   -48 -71 -6

############   t2  #################
System.out.println(new String(t2.toString()));
//结果是:中国

test01.printByte(t2.getBytes());  // 打印数组的方法
//结果是:-28   -72 -83 -27 -101    -67     

说明一下 Text不是简单的封装String 这句话。
如果你看源码的话,你可以看到,Text类里核心是一个byte数组,而String类的核心是一个char数组。
java的默认编码格式为Unicode,Text默认且惟一的编码格式为UTF-8。

用Text.set( byte[] )赋值时,是把String的char[]数组按照Unicode编码格式找到 ‘中国’ ,然后转换成byte[] ,再赋值给t1的核心byte[] ,
而使用Text.set( string )赋值时,把String的char[]数组按照Unicode编码格式找到 ‘中国’ ,然后查找utf-8编码表,依次查出 ‘中国’ 的byte,然后赋给t2的核心byte[]。所以说 t1中保存的Unicode(也就是最原始的编码格式) 编码的字节。t2保存的是经过转换的,utf-8编码格式的字节。

然后就是Text.toString() 方法了,Text会默认把自己核心的byte[]数组用utf-8解码出一个String,纵使byte[]不是utf-8编码的。这就解释了为什么t1.toString() 打印出来的是乱码,因为t1的toString方法把 -42 -48 -71 -6 按utf-8解码,然后就是乱码了,t2.toString()打印出来是 ‘中国’的原因是 其核心byte[] 就是由utf-8编码的,在用 utf-8 解码,自然不会出错。

我们出现乱码的原因跟 t1 乱码的原因一样,在Task中,我们读入文件时,是按字节读入的,然后用Text.set( byte[] )方法赋值给map函数中第二个参数value。而输出代码是在TextOutputFormat类的writeObject方法,其源码如下:

...
## TextOutputFormat规定死了,就是要用utf-8解码
private static final String utf8 = "UTF-8";
...
 private void writeObject(Object o) throws IOException {
      if (o i
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值