Scala 使用UTF-8编码在Spark中写入CSV(德语字符)时出现问题
我有一组(全球)公司的数据,其中有许多公司有外国名称 我首先使用以下方法导入拼花地板数据:Scala 使用UTF-8编码在Spark中写入CSV(德语字符)时出现问题,scala,dataframe,apache-spark,pyspark,Scala,Dataframe,Apache Spark,Pyspark,我有一组(全球)公司的数据,其中有许多公司有外国名称 我首先使用以下方法导入拼花地板数据: val df = spark.read.format("parquet").load("import path"). 我做了一些过滤和操作,当我将数据写入csv时,即使在我指定了编码之后,它也会显示奇怪的符号 卫生部沃思 基茨比¼赫尔乡村俱乐部 科拉斯瓦酒店™ednÃodb。科拉™埃梅塞尔 如何导出数据以便准确表示外来字符 df.coalesce(1). write.
val df = spark.read.format("parquet").load("import path").
我做了一些过滤和操作,当我将数据写入csv时,即使在我指定了编码之后,它也会显示奇怪的符号
- 卫生部沃思
- 基茨比¼赫尔乡村俱乐部
- 科拉斯瓦酒店™ednÃodb。科拉™埃梅塞尔
df.coalesce(1).
write.
mode(SaveMode.Overwrite).
format("csv").
option("header", true).
option("encoding", "UTF-8").
partitionBy("Region").
save("path")
您使用的是哪个Apache Spark版本?编码选项从2.4.0开始就可用,您可以在与中看到
此外,根据上面引用的文档,如果它是
UTF-8
,您不需要设置编码,因为它实际上是默认编码。我认为您必须为德语字符指定正确的编码。或者您正在打开的编辑器正在通过其自身编码损坏字符(可能是编辑器错误)。通常,utf-8和iso-8859都将以相同的方式进行编码。与@GPI聊天后,我还测试了以下utf-8格式的代码。我使用intellijeditor打开了生成的文本文件,输出结果与intellijeditor相同。
更新/结论:以下使用iso或utf-8的方法应以相同的方式工作。可能是他打开的OPS文本编辑器导致了这个问题。问题根本就不是问题。 获取德语字符数据样本,并在文件系统中再次保存为csv 下面是示例和代码
package examples
import org.apache.log4j.Level
import org.apache.spark.sql.{DataFrame, SaveMode, SparkSession}
object GermanCSV extends App {
val logger = org.apache.log4j.Logger.getLogger("org")
logger.setLevel(Level.WARN)
val spark = SparkSession.builder().appName(this.getClass.getName).master("local").getOrCreate()
import spark.implicits._
val mycsvdata =
"""
|rank,freq,Infinitiv,Unreg,Trans,"Präsens_ich","Präsens_du","Präsens_er, sie, es","Präteritum_ich","Partizip II","Konjunktiv II_ich","Imperativ Singular","Imperativ Plural",Hilfsverb
|3,3796784,sein,"","",bin,bist,ist,war,gewesen,"wäre",sei,seid,sein
|8,1618550,haben,"","",habe,hast,hat,hatte,gehabt,"hätte",habe,habt,haben
|10,1379496,einen,"","",eine,einst,eint,einte,geeint,einte,eine,eint,haben
|12,948246,werden,"","",werde,wirst,wird,wurde,geworden,"würde",werde,werdet,sein
""".stripMargin.lines.toList.toDS
val csvdf: DataFrame = spark.read.option("header", true)
.option("header", true)
.csv(mycsvdata)
println("orginal data")
csvdf.show(false)
println("Writing in to a csv file with ISO-8859-1 encoding way , handling german characters")
csvdf.coalesce(1).
write.
mode(SaveMode.Overwrite).
format("csv").
option("header", true)
.option("encoding", "ISO-8859-1")
.save("data/iso8859-1")
}
结果:
[2020-04-22 10:26:36,598] WARN Unable to load native-hadoop library for your platform... using builtin-java classes where applicable (org.apache.hadoop.util.NativeCodeLoader:62)
orginal data
+----+-------+---------+-----+-----+-----------+----------+-------------------+--------------+-----------+-----------------+------------------+----------------+---------+
|rank|freq |Infinitiv|Unreg|Trans|Präsens_ich|Präsens_du|Präsens_er, sie, es|Präteritum_ich|Partizip II|Konjunktiv II_ich|Imperativ Singular|Imperativ Plural|Hilfsverb|
+----+-------+---------+-----+-----+-----------+----------+-------------------+--------------+-----------+-----------------+------------------+----------------+---------+
|3 |3796784|sein |null |null |bin |bist |ist |war |gewesen |wäre |sei |seid |sein |
|8 |1618550|haben |null |null |habe |hast |hat |hatte |gehabt |hätte |habe |habt |haben |
|10 |1379496|einen |null |null |eine |einst |eint |einte |geeint |einte |eine |eint |haben |
|12 |948246 |werden |null |null |werde |wirst |wird |wurde |geworden |würde |werde |werdet |sein |
+----+-------+---------+-----+-----+-----------+----------+-------------------+--------------+-----------+-----------------+------------------+----------------+---------+
Writing in to a csv file with ISO-8859-1 encoding way , handling german characters
根据代码数据/iso8859-1保存csv不更改数据。。。如下图所示:
“被准确地表示出来?”“你想用英语显示它们是什么意思?这些公司实际上是德语,所以数据应该有Ä、Ö、Ü等字符。我想大胆猜测一下:你确定输出文件不正确吗?它很可能是用于可视化输出文件的文本编辑器,而不是使用UTF显示内容。您必须确保“损坏”发生在哪里:您对拼花地板文件的读取是否正常?还是在你操纵文本的时候?还是在你写文件的时候?或者是你检查文件的文本编辑器?当有疑问时,我倾向于用十六进制查看器打开文件,检查字节,而不是它们的文本解释。@BennyLin我的答案有效或不让我知道。不确定你的观点,这里DataFrameReader.csv(ds:Dataset[String])
从字符串(而不是字节)执行csv解析。因此,在读取部分中定义编码是无用的。举个例子:spark.read.option(“header”,true)。option(“encoding”,“doesNotExistEver”).csv(mycsvdata)
在代码中的作用是一样的。这意味着,IMHO,你的代码相当于OP。这将倾向于证明OP实际上在其实现中没有任何问题,但在用于执行其检查的工具中(例如:它以ISO拉丁模式打开UTF文件)。使用dataframereader.csv,我只准备了带有特殊字符的测试数据,并以编码ISO-8859-1编写,以查看源数据是否在更改。在@Benny lins的案例中,他无法显示源文件(拼花地板)中的特殊字符,因为他使用utf-8编码将其转换为csv。所以我要求他改变编码。对于这个例子,我们展示了一个特殊的德语字符。但是当你从拼花地板读取数据时,没有指定编码,拼花地板格式本身进行编码(或者我弄错了?)。如果我没弄错的话,OP没有任何东西可以更改以匹配您的代码,并且损坏(如果有)只能发生在与您的答案中OP相同的编写阶段(如果我没弄错的话,请再说一遍)。是的,您是对的,在阅读时没有指定编码。。。正如我在我的例子中错误地做的那样。在编写时,我们需要指定编码csvdf.coalesce(1)。写模式(SaveMode.Overwrite)。格式(“csv”)。选项(“header”,true)。选项(“encoding”,“ISO-8859-1”)。保存(“data/iso8859-1”)
我修改了示例。但我的最终目的是告诉大家,我们在编写时必须使用ISO-8859-1。我没有看到任何字符在ISO 8859-1中是可编码的,而在UTF8中是不可编码的。当ISO 8859 1没有失败时,UTF8没有理由失败。输出编码也可能是一项技术要求,因此这里可能没有选择的余地。我再一次得出了同样的结论:OP使用的文本编辑器读取了一个带有ISO编码的有效UTF文件,这使得它看起来像是写入失败/数据损坏,而实际上是控制过程失败,而不是输出的生成。这是迄今为止最有可能的解释,直到被证明是错误的。
[2020-04-22 10:26:36,598] WARN Unable to load native-hadoop library for your platform... using builtin-java classes where applicable (org.apache.hadoop.util.NativeCodeLoader:62)
orginal data
+----+-------+---------+-----+-----+-----------+----------+-------------------+--------------+-----------+-----------------+------------------+----------------+---------+
|rank|freq |Infinitiv|Unreg|Trans|Präsens_ich|Präsens_du|Präsens_er, sie, es|Präteritum_ich|Partizip II|Konjunktiv II_ich|Imperativ Singular|Imperativ Plural|Hilfsverb|
+----+-------+---------+-----+-----+-----------+----------+-------------------+--------------+-----------+-----------------+------------------+----------------+---------+
|3 |3796784|sein |null |null |bin |bist |ist |war |gewesen |wäre |sei |seid |sein |
|8 |1618550|haben |null |null |habe |hast |hat |hatte |gehabt |hätte |habe |habt |haben |
|10 |1379496|einen |null |null |eine |einst |eint |einte |geeint |einte |eine |eint |haben |
|12 |948246 |werden |null |null |werde |wirst |wird |wurde |geworden |würde |werde |werdet |sein |
+----+-------+---------+-----+-----+-----------+----------+-------------------+--------------+-----------+-----------------+------------------+----------------+---------+
Writing in to a csv file with ISO-8859-1 encoding way , handling german characters
rank,freq,Infinitiv,Unreg,Trans,Präsens_ich,Präsens_du,"Präsens_er, sie, es",Präteritum_ich,Partizip II,Konjunktiv II_ich,Imperativ Singular,Imperativ Plural,Hilfsverb
3,3796784,sein,"","",bin,bist,ist,war,gewesen,wäre,sei,seid,sein
8,1618550,haben,"","",habe,hast,hat,hatte,gehabt,hätte,habe,habt,haben
10,1379496,einen,"","",eine,einst,eint,einte,geeint,einte,eine,eint,haben
12,948246,werden,"","",werde,wirst,wird,wurde,geworden,würde,werde,werdet,sein