日志的格式是GBK编码的,而hadoop上的编码是用UTF-8写死的,导致最终输出乱码。

研究了下Java的编码问题。

网上其实对spark输入文件是GBK编码有现成的解决方案,具体代码如下

import org.apache.hadoop.io.LongWritable
import org.apache.hadoop.io.Text
import org.apache.hadoop.mapred.TextInputFormat rdd = ctx.hadoopFile(file_list, classOf[TextInputFormat],
classOf[LongWritable], classOf[Text]).map(
pair => new String(pair._2.getBytes, , pair._2.getLength, "GBK"))

这种想法的来源是基于

public static Text transformTextToUTF8(Text text, String encoding) {
String value = null;
try {
value = new String(text.getBytes(), , text.getLength(), encoding);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new Text(value);
}

但这种方法还有一个问题,

大家都知道gbk是2~3个字节编码的。如果日志中按照直接截断,导致按照gbk读取文件的时候,将后面的分隔符\t一并读取了 ,导致按照\t split的时候,字段的个数不对(或者说顺序错位了)。

这个时候,需要找到一种单字节的解析方案,即 ISO-8859-1编码。代码如下

rdd = ctx.hadoopFile(file_list, classOf[TextInputFormat],
classOf[LongWritable], classOf[Text]).map(
pair => new String(pair._2.getBytes, , pair._2.getLength, "ISO-8859-1"))

但这又带来了一个问题,即输出的结果(按照UTF-8存储)是乱码,不可用。

如果我们换一种思路来考虑这个问题,Java或scala中如何将一个gbk文件转换为UTF8?网上有很多的现成的代码,具体到我们的场景,以行为单位处理的话,示例代码如下

public class Encoding {
private static String kISOEncoding = "ISO-8859-1";
private static String kGBKEncoding = "GBK";
private static String kUTF8Encoding = "UTF-8"; public static void main(String[] args) throws UnsupportedEncodingException {
try {
File out_file = new File(args[1]);
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(out_file), kUTF8Encoding));
List<String> lines = Files.readAllLines(Paths.get(args[0]), Charset.forName(kGBKEncoding));
for (String line : lines) {
out.append(line).append("\n");
}
out.flush();
out.close();
} catch (IOException e) {
System.out.println(e);
}
}
}

如上的代码给了我们一个启示,即在写入文件的时候,系统自动进行了编码的转换,我们没必要对进行单独的直接转换处理。

通过查询资料,Java中字符编码是内部编码,即字节流按照编码转化为String。

所谓结合以上两点认识,我们模拟在spark上以ISO-8859-1

打开文件和以UTF-8写入文件的过程,发现只需要将其强制转换为GBK的string即可,最终得到的文件以UTF-8打开不是乱码,具体代码如下。

public class Encoding {
private static String kISOEncoding = "ISO-8859-1";
private static String kGBKEncoding = "GBK";
private static String kUTF8Encoding = "UTF-8"; public static void main(String[] args) throws UnsupportedEncodingException {
try {
File out_file = new File(args[1]);
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(out_file), kUTF8Encoding));
List<String> lines = Files.readAllLines(Paths.get(args[0]), Charset.forName(kISOEncoding));
for (String line : lines) {
String gbk_str = new String(line.getBytes(kISOEncoding), kGBKEncoding);
out.append(gbk_str).append("\n");
}
out.flush();
out.close();
} catch (IOException e) {
System.out.println(e);
}
}
}

完美的解决了。。。花费了一个工作日解决才解决的问题,对Java还是不够熟练啊。

总结出来,希望对大家有用。

总结

1. 要举一反三

2. 学会google,最近我就指望着它活着了。

spark 中文编码处理的更多相关文章

  1. 基于spark的plsa实现

    PLSA.py # coding:utf8 from pyspark import SparkContext from pyspark import RDD import numpy as np fr ...

  2. Spark踩坑记——Spark Streaming+Kafka

    [TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...

  3. Spark RDD 核心总结

    摘要: 1.RDD的五大属性 1.1 partitions(分区) 1.2 partitioner(分区方法) 1.3 dependencies(依赖关系) 1.4 compute(获取分区迭代列表) ...

  4. spark处理大规模语料库统计词汇

    最近迷上了spark,写一个专门处理语料库生成词库的项目拿来练练手, github地址:https://github.com/LiuRoy/spark_splitter.代码实现参考wordmaker ...

  5. Hive on Spark安装配置详解(都是坑啊)

    个人主页:http://www.linbingdong.com 简书地址:http://www.jianshu.com/p/a7f75b868568 简介 本文主要记录如何安装配置Hive on Sp ...

  6. Spark踩坑记——数据库(Hbase+Mysql)

    [TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...

  7. Spark踩坑记——初试

    [TOC] Spark简介 整体认识 Apache Spark是一个围绕速度.易用性和复杂分析构建的大数据处理框架.最初在2009年由加州大学伯克利分校的AMPLab开发,并于2010年成为Apach ...

  8. Spark读写Hbase的二种方式对比

    作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 一.传统方式 这种方式就是常用的TableInputFormat和TableOutputForm ...

  9. (资源整理)带你入门Spark

    一.Spark简介: 以下是百度百科对Spark的介绍: Spark 是一种与 Hadoop 相似的开源集群计算环境,但是两者之间还存在一些不同之处,这些有用的不同之处使 Spark 在某些工作负载方 ...

随机推荐

  1. poi自定义颜色设置(转)

    原文链接  http://javapolo.iteye.com/blog/1604501 最近在项目的开发中使用到了apache poi,该组件可以让我们方便的操作excell,该工具非常容易上手,但 ...

  2. [置顶] Git 配置SSH简单玩法?

    > 第一步下载git点击直接下载 他会检测您的系统当前是64bit还是32bit安装过程不再啰嗦反正就是Next Next Next Finish 第二步这里你可以下载TortoiseGit点击 ...

  3. Gatling:开源压力测试框架之入门

    Gatling是一款开源的压力测试工具,基于Scala, Akka and Netty. 可录制测试脚本,也可以手动编写脚本,适合有编程经验的测试人员使用: 支持测试用例的参数化,可以使用csv.js ...

  4. C++常量const

    常量折叠概念 常量折叠表面上的效果和宏替换是一样的,只是“效果上是一样的”,而两者真正的区别在于,宏是字符常量,在预编译宏替换完成后,该宏名字会消失,所有对宏的引用已经全部被替换为它所对应的值,编译器 ...

  5. Window Handle介绍

    HANDLE(句柄)是Windows操作系统中的一个概念.在Windows程序中,有各种各样的资源(窗口.图标.光标等),系统在创建这些资源时会为它们分配内存,并返回标示这些资源的标示号,即句柄.句柄 ...

  6. Kubernetes安装部署演示介绍

    四.安装k8s 1.安装 使用的是k8s 1.2.4版本. 将kubernetes.tar.gz 上传主机,并解压. tar -xzvf kubernetes.tar.gz cd kubernetes ...

  7. POJ1742:Coins

    浅谈\(DP\):https://www.cnblogs.com/AKMer/p/10437525.html 题目传送门:http://poj.org/problem?id=1742 多重背包,每个物 ...

  8. Docker技术初体验

    什么是Docker Docker技术和虚拟机技术类似,他们都能在一个Host系统中划分出多个相互独立隔离的运行环境.借助官方配图: 虚拟机的示意图是这样的 我们需要为每个虚拟机安装自己的操作系统,即使 ...

  9. php跨域问题

    http://www.cnblogs.com/xiezn/p/5651093.html

  10. 【转】 Pro Android学习笔记(九三):AsyncTask(2):小例子

    目录(?)[-] 继承AsyncTask UI操作接口 使用AsyncTask 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn. ...