使用 iso-8859-1 文件读取 CSV 和文本文件的 Spark 的不同行为

Different behavior of Spark reading CSV and text file using iso-8859-1 file

提问人:Heitor Barbieri 提问时间:11/7/2023 最后编辑:Gaël JHeitor Barbieri 更新时间:11/7/2023 访问量:51

问:

问题:我在使用文本文件进行编码转换时遇到了问题,当我使用 csv 文件时不会发生这个问题。

操作系统:Ubuntu的 23.10

Scala:2.13.12

火花:3.5.0

法典:

package sct

import org.apache.spark.sql.{DataFrame, DataFrameReader, Dataset, SparkSession}

object EncodingApp {
  def main(args: Array[String]): Unit = {
    val inFile: String = "ISO_8859_1.txt" // iso-8859-1 encoded file with only one line: "José, André"
    val spark: SparkSession = SparkSession.builder.appName("Encoding Application")
      .master("local[*]").getOrCreate()
    val reader: DataFrameReader = spark.read.option("encoding", "ISO-8859-1")

    val text: Dataset[String] = reader.textFile(inFile)
    val csv: DataFrame = reader.csv(inFile)

    text.show()
    csv.show()

    spark.close()
    spark.stop()
  }
}

输出:

+-----------+
|      value|
+-----------+
|Jos�, Andr�|
+-----------+

+----+------+
| _c0|   _c1|
+----+------+
|José| André|
+----+------+

我做错了什么?

Scala Apache Spark 字符编码

评论

1赞 Kombajn zbożowy 11/7/2023
这回答了你的问题吗?使用非 UTF-8 编码的 spark 读取 wholeTextFiles

答:

1赞 mamonu 11/7/2023 #1

观察到的行为差异可能是由于 Spark DataFrameReader 处理文本文件与 CSV 文件的方式,尤其是在读取过程中应用编码的方式。

我会按如下方式处理这个问题。首先导入所需的库:

import spark.implicits._
import org.apache.spark.sql.functions._

然后将文本读取为二进制文件,然后我们可以应用 正确的编码

val text = spark.read
  .format("binaryFile")
  .load("ISO_8859_1.txt")
  .select(col("content"))
  .as[Array[Byte]]
  .flatMap(bytes => new String(bytes, "ISO-8859-1")
  .split("\n")) // Split lines here
  .toDF("value")

text.show()

但是,虽然读取正确,但现在数据仍在一列中

+-----------+
|      value|
+-----------+
|José, André|
+-----------+

因此,为了创建所需的数据帧 您可以执行以下操作:

val csvData = text
  .withColumn("_tmp", split(col("value"), ","))
  .select(
    trim(col("_tmp").getItem(0)).as("_c0"),
    trim(col("_tmp").getItem(1)).as("_c1")
  )

csvData.show()

结果:

+----+-----+
| _c0|  _c1|
+----+-----+
|José|André|
+----+-----+

注意:你可能需要把整个事情变成一个函数或其他东西,然后根据口味进行更改。但我认为这是一个好的开始。

评论

0赞 Heitor Barbieri 11/9/2023
成功了。谢谢。但我认为输入字符编码规范应该位于 DataFrame 类中,而不是位于 DataFrameReader 中,以避免尝试使用它从文件中读取文本的错误。