我写了一个Spark应用程序,它从CSV文件中读取,过滤和打印数据,保存在HDFS中。当我将CSV下载到我的电脑并打开它时,一切正常,所有的变音符号都能正确显示。但是:当我运行我的应用程序时,变音符号显示不正确,它们都显示为�
。
是否有可能设置编码以通过Spark中的.textFile事务加载csv或“转换”输入?
这似乎是一个无法解决的问题: https://issues.apache.org/jira/browse/SPARK-1849
由于文件的UTF-8编码而出现问题。似乎,使用.hadoopFile
有一种解决方法,但我不知道如何使用此方法。有人可以帮忙吗?
尝试了以下代码,但没有成功:
test.txt文件:
ÄPPLE
APPLE
ÖPPLE
ÜPPLE
Spark程序:
public static void main(String[] args) throws ClassNotFoundException {
String inputFile = args[0];
SparkConf sparkConf = new SparkConf().setAppName("EdekaOwgCheckUmlauts");
sparkConf.registerKryoClasses(new Class<?>[]{
Class.forName("org.apache.hadoop.io.LongWritable"),
Class.forName("org.apache.hadoop.io.Text")
});
JavaSparkContext sc = new JavaSparkContext(sparkConf);
JavaRDD<Text> input = sc.hadoopFile(inputFile, TextInputFormat.class, LongWritable.class, Text.class).map(new Function<Tuple2<LongWritable,Text>, Text>() {
@Override
public Text call(Tuple2<LongWritable, Text> v1) throws Exception {
return v1._2();
}
});
JavaRDD<Text> filtered = input.filter(new Function<Text, Boolean>() {
@Override
public Boolean call(Text v1) throws Exception {
return v1.toString().toLowerCase().contains("pple"); // LOOK FOR ÄPPLE, APPLE etc.
}
});
List<Text> collected = filtered.collect();
System.out.println("=== PRINT ===");
for(Text row : collected) {
try {
System.out.println(row.decode(row.getBytes()));
} catch (CharacterCodingException e) {
e.printStackTrace();
}
}
}
控制台输出:
�PPLE
APPLE
�PPLE
�PPLE
该文件使用charset iso-8859-1
进行编码致电file -i myfile.csv
会显示以下信息:
myfile.csv: text/plain; charset=iso-8859-1
我尝试使用以下代码将此charset转换为utf-8:
JavaRDD<String> inputRDD = sc.textFile(inputFile);
List<String> asList = inputRDD.collect();
for(String a : asList) {
try {
byte[] isoBytes = a.getBytes("ISO-8859-1");
System.out.println(new String(isoBytes, "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
没有成功,控制台会打印?
而不是ä,ö,ü...
答案 0 :(得分:2)
这是使用hadoopFile和从右字符集重新编码的最短版本(iso-8859-1到UTF-8):
import org.apache.hadoop.io.LongWritable
import org.apache.hadoop.io.Text
import org.apache.hadoop.mapred.TextInputFormat
val file=sc.hadoopFile[LongWritable, Text, TextInputFormat]("/file...").
mapPartitions(
_.map(line => new String(line._2.getBytes, 0, line._2.getLength, "iso-8859-1"))
)
希望有所帮助。
这只能在使用spark textFile读取文件后使用hadoop.io.Text而不是字符串。
或许有人理解为什么?
答案 1 :(得分:1)
您可以编写自己的自定义TextInputFormat并将其与newAPIHadoopFile一起使用。 TextInputFormat使用Text.class来处理以UTF-8存储数据的数据:主要思想是使用String.class(使用正确的编码)。
按照TextInputFormat类重新编写需要更改的内容。这包括重写您自己的RecordReader,LineRecordReader,SplitLineReader。这不应该太复杂,但不幸的是很长。
然后您应该可以使用这样的自定义文本输入格式:
// JavaSparkContext sc
//File path path
JavaPairRDD<String, BytesWritable> zip = sc.newAPIHadoopFile(path,
CustomTextInputFormat.class,
LongWritable.class,
String.class,
sc.hadoopConfiguration());
希望这有帮助。