hadoop的hdfs文件系统中,默认的是utf-8, 故你上传的文件是要设置成utf-8。当输入的是gbk,有该如何?

输入是GBK文件, 输出也是 GBK 文件的示例代码:

Hadoop处理GBK文本时,发现输出出现了乱码,原来HADOOP在涉及编码时都是写死的UTF-8,如果文件编码格式是其它类型(如GBK),则会出现乱码。

此时只需在mapper或reducer程序中读取Text时,使用transformTextToUTF8(text, "GBK");进行一下转码,以确保都是以UTF-8的编码方式在运行。

  1. public static Text transformTextToUTF8(Text text, String encoding) {
  2. String value = null;
  3. try {
  4. value = new String(text.getBytes(), 0, text.getLength(), encoding);
  5. } catch (UnsupportedEncodingException e) {
  6. e.printStackTrace();
  7. }
  8. return new Text(value);
  9. }
 

这里核心代码是: String line=new String(text.getBytes(),0,text.getLength(),"GBK"); //这里的value是Text类型

若直接使用 String line=value.toString(); 会输出乱码, 这是由Text这个Writable类型造成的。初学时,一直认为和LongWritable对long的封装一样,Text类型是String的Writable封装。但其实Text和String还是有些区别,它是一种UTF-8格式的Writable,而Java中的String是Unicode字符。所以直接使用value.toString()方法,会默认其中的字符都是UTF-8编码过的,因而原本GBK编码的数据使用Text读入后直接使用该方法就会变成乱码。

正确的方法是将输入的Text类型的value转换为字节数组(value.getBytes()),使用String的构造器String(byte[] bytes, int offset, int length, Charset charset),通过使用指定的charset解码指定的byte子数组,构造一个新的String。

如果需要map/reduce输出其它编码格式的数据,需要自己实现OutputFormat,在其中指定编码方式,而不能使用默认的TextOutputFormat。

具体的范例可以见淘宝数据平台与产品部官方博客上的博文 http://www.tbdata.org/archives/244 。

来自:  Hadoop的map/reduce作业输入非UTF-8编码数据的处理原理

以下摘自 淘宝数据平台与产品部官方博客:

1 中文问题
    从url中解析出中文,但hadoop中打印出来仍是乱码?我们曾经以为hadoop是不支持中文的,后来经过查看源代码,发现hadoop仅仅是不支持以gbk格式输出中文而己。

    这是TextOutputFormat.class中的代码,hadoop默认的输出都是继承自FileOutputFormat来的,FileOutputFormat的两个子类一个是基于二进制流的输出,一个就是基于文本的输出TextOutputFormat。

    public static class TextOutputFormat<K, V> extends FileOutputFormat<K, V> {
  protected static class LineRecordWriter<K, V>
    implements RecordWriter<K, V> {
    private static final String utf8 = “UTF-8″;//这里被写死成了utf-8
    private static final byte[] newline;
    static {
      try {
        newline = “\n”.getBytes(utf8);
      } catch (UnsupportedEncodingException uee) {
        throw new IllegalArgumentException(“can’t find ” + utf8 + ” encoding”);
      }
    }

    public LineRecordWriter(DataOutputStream out, String keyValueSeparator) {
      this.out = out;
      try {
        this.keyValueSeparator = keyValueSeparator.getBytes(utf8);
      } catch (UnsupportedEncodingException uee) {
        throw new IllegalArgumentException(“can’t find ” + utf8 + ” encoding”);
      }
    }

    private void writeObject(Object o) throws IOException {
      if (o instanceof Text) {
        Text to = (Text) o;
        out.write(to.getBytes(), 0, to.getLength());//这里也需要修改
      } else {
        out.write(o.toString().getBytes(utf8));
      }
    }
 …
}
    可以看出hadoop默认的输出写死为utf-8,因此如果decode中文正确,那么将Linux客户端的character设为utf-8是可以看到中文的。因为hadoop用utf-8的格式输出了中文。
    因为大多数数据库是用gbk来定义字段的,如果想让hadoop用gbk格式输出中文以兼容数据库怎么办?
    我们可以定义一个新的类:
    public class GbkOutputFormat<K, V> extends FileOutputFormat<K, V> {
  protected static class LineRecordWriter<K, V>
    implements RecordWriter<K, V> {
    //写成gbk即可
    private static final String gbk = “gbk”;

    private static final byte[] newline;
    static {
      try {
        newline = “\n”.getBytes(gbk);
      } catch (UnsupportedEncodingException uee) {
        throw new IllegalArgumentException(“can’t find ” + gbk + ” encoding”);
      }
    }

    public LineRecordWriter(DataOutputStream out, String keyValueSeparator) {
      this.out = out;
      try {
        this.keyValueSeparator = keyValueSeparator.getBytes(gbk);
      } catch (UnsupportedEncodingException uee) {
        throw new IllegalArgumentException(“can’t find ” + gbk + ” encoding”);
      }
    }

    private void writeObject(Object o) throws IOException {
      if (o instanceof Text) {
             //  Text to = (Text) o;
             //  out.write(to.getBytes(), 0, to.getLength());
            //  
} else {

        out.write(o.toString().getBytes(gbk));
      }
    }
 …
}
    然后在mapreduce代码中加入conf1.setOutputFormat(GbkOutputFormat.class)
    即可以gbk格式输出中文。

详见有道笔记: http://note.youdao.com/share/?id=04678102d70bae8334b26df2c9c4a961&type=note

Hadoop 中文编码相关问题 -- mapreduce程序处理GBK编码数据并输出GBK编码数据(转)的更多相关文章

  1. 攻城狮在路上(陆)-- 配置hadoop本地windows运行MapReduce程序环境

    本文的目的是实现在windows环境下实现模拟运行Map/Reduce程序.最终实现效果:MapReduce程序不会被提交到实际集群,但是运算结果会写入到集群的HDFS系统中. 一.环境说明:     ...

  2. Eclipse下使用Hadoop单机模式调试MapReduce程序

    在单机模式下Hadoop不会使用HDFS,也不会开启任何Hadoop守护进程,所有程序将在一个JVM上运行并且最多只允许拥有一个reducer 在Eclipse中新创建一个hadoop-test的Ja ...

  3. Hadoop YARN上运行MapReduce程序

    (1)配置集群 (a)配置hadoop-2.7.2/etc/hadoop/yarn-env.sh 配置一下JAVA_HOME export JAVA_HOME=/home/hadoop/bigdata ...

  4. 高可用Hadoop平台-运行MapReduce程序

    1.概述 最近有同学反应,如何在配置了HA的Hadoop平台运行MapReduce程序呢?对于刚步入Hadoop行业的同学,这个疑问却是会存在,其实仔细想想,如果你之前的语言功底不错的,应该会想到自动 ...

  5. 在hadoop上进行编写mapreduce程序,统计关键词在text出现次数

    mapreduce的处理过程分为2个阶段,map阶段,和reduce阶段.在要求统计指定文件里的全部单词的出现次数时. map阶段把每一个关键词写到一行上以逗号进行分隔.并初始化数量为1(同样的单词h ...

  6. Hadoop中文编码乱码相关问题

    mapreduce程序处理GBK编码数据并输出GBK编码数据, hadoop涉及输出文本的默认输出编码统一用没有BOM的UTF-8的形式,但是对于中文的输出window系统默认的是GBK,有些格式文件 ...

  7. Hadoop_05_运行 Hadoop 自带 MapReduce程序

    1. MapReduce使用 MapReduce是Hadoop中的分布式运算编程框架,只要按照其编程规范,只需要编写少量的业务逻辑代码即可实现 一个强大的海量数据并发处理程序 2. 运行Hadoop自 ...

  8. 使用Eclipse编译运行MapReduce程序 Hadoop2.6.0_Ubuntu/CentOS

    使用Eclipse编译运行MapReduce程序 Hadoop2.6.0_Ubuntu/CentOS  2014-10-10 (updated: 2016-05-22) 64246 153 本教程介绍 ...

  9. Hadoop(十三)分析MapReduce程序

    前言 刚才发生了悲伤的一幕,本来这篇博客马上就要写好的,花了我一晚上的时间.但是刚才电脑没有插电源就没有了.很难受!想哭,但是没有办法继续站起来. 前面的一篇博文中介绍了什么是MapReduce,这一 ...

随机推荐

  1. groovy–运算符重载

    Groovy支持运算符重载,各种运算符被映射到普通的java对象的方法调用,这就使得开发者可以利用运算符重载的优势来编写自己的Java或者groovy对象. 下面的表格描述了groovy中的操作符所映 ...

  2. Using a Comparison Function for the Key Type

    (这是C++系列随笔的第二篇,这一系列是我练习C++而查的资料) C++ Primer 5th. Ed. pp. 425 ---------------------- Using a Comparis ...

  3. Shell编程检测监控mysql的CPU占用率

    shell编程很强大! 网站访问量大的时候mysql的压力就比较大,当mysql的CPU利用率超过300%的时候就不能提供服务了,近乎卡死状态,这时候最好的方法就是重启mysql服务.由于这种事具有不 ...

  4. JAVA命令大全

    1.java.exe:======================运行java程序,这个相信每一位用Java的人知道了. 2.javac.exe:======================编译的Ja ...

  5. git常见问题解决办法

    1,git status乱码 git config --global core.quotepath false 执行完后再使用时,就显示正常了

  6. C#面向对象面试题集锦

    1.简述C#中的虚方法 答:注意:当使用virtual关键字修饰符后,不允许再同时使用abstract,static,或override关键字进行修饰 使用virtual关键字修饰的方法就是虚方法,虚 ...

  7. update操作多张表

    sql 语句多张表UPDATE用法一.当用一个表中的数据来更新另一个表中的数据,T-SQL提供多种写法(下面列出了二种),但建议用第一种写法,虽然传统,但结构清晰.飞.飞Asp技术乐园并且要注意,当用 ...

  8. editplus如何插入当前时间_Ctrl+D

    之前的工作日志一般都是用excel来写的,但那个占用内存有点大,有时也比较麻烦,有时内容一行没办法显示,会自动截断,有点类似缩略图,无法一目了然 习惯了使用editplus,轻便快速,不占内存.但是有 ...

  9. Spell checker(暴力)

    Spell checker Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 20188   Accepted: 7404 De ...

  10. 关于Eclipse部署openfire3.8.2源码的体会

    因为公司要做人际银行的一个项目需要openfire(服务器)+asmack(客户端),所以需要对消息的推送及消息发送知识的积累.所以需要研究xmpp,以前不是很了解这个技术,现在需要学习.首先就得部署 ...