提问人:Heitor Barbieri 提问时间:11/7/2023 最后编辑:Gaël JHeitor Barbieri 更新时间:11/7/2023 访问量:51
使用 iso-8859-1 文件读取 CSV 和文本文件的 Spark 的不同行为
Different behavior of Spark reading CSV and text file using iso-8859-1 file
问:
问题:我在使用文本文件进行编码转换时遇到了问题,当我使用 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é|
+----+------+
我做错了什么?
答:
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 中,以避免尝试使用它从文件中读取文本的错误。
评论