问题描述
初学大数据处理框架 spark ,在读入实验的数据时,遇到了经典的字符编码问题
实验环境:
os:ubuntu 18.04
spark: version 2.4.0
使用spark读入的文件编码是 gbk,大小是10Gb
根据spark的文档介绍,使用的函数是
SparkConf conf = new SparkConf().setAppName("first").setMaster("local");
JavaRDD<String> distFile = sc.textFile("data.txt");
由于这个函数只能固定使用UTF-8编码格式读取文件
然后读到的结果就成了 “����” 这个样子
或者就是 “锟斤拷” 这个样子 ,就是 “手持两把锟斤拷,口中疾呼烫烫烫。脚踏千朵屯屯屯,笑看万物锘锘锘” 这个编码梗的由来
一般来说,这个问题多出现于GBK与UTF-8编码互相转换时。GBK编码是windows系统的编码格式,而UTF-8是linux系统的编码格式,而且Git等开源软件也都使用UTF-8编码,所以简单了解这种编码问题就是一件十分必要的事情。
解决问题
首先的思路是在读入文件之前,先用编辑器把GBK编码的文件转成UTF-8编码的文件,然后再使用上面的代码读入数据。
这个思路一定是可以的,但是这里有一个问题,我实验使用的文件大小是10Gb,编辑器要想处理这么大的文件,基本都会直接打不开或者处理时卡死。
既然是使用大数据计算框架,就应该用spark自己来解决
Java语言的写法是调用 hadoopFile()来读取文件,然后将读到的RDD map(映射)成一个使用GBK编码新生成的字符串
调用map(p -> new String(p._2.getBytes(), 0, p._2.getLength(), “GBK”)),即可解决问题。
完整代码如下:
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.SparkConf;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapred.TextInputFormat;
public class main {
public static void main(String[] args) {
String filePath = "./data.dat";
SparkConf conf = new SparkConf().setAppName("encoding_problem").setMaster("local");
JavaSparkContext sc = new JavaSparkContext(conf);
// read file use encoding format: GBK
JavaRDD<String> fileRDD = sc.hadoopFile(filePath, TextInputFormat.class, LongWritable.class, Text.class).map(p -> new String(p._2.getBytes(), 0, p._2.getLength(), "GBK"));
}
}