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