当最后一列名称包含空格时,Spark 无法读取 CSV

Spark fails to read CSV when last column name contains spaces

我有一个如下所示的 CSV:

+-----------------+-----------------+-----------------+
| Column One      | Column Two      | Column Three    |
+-----------------+-----------------+-----------------+
| This is a value | This is a value | This is a value |
+-----------------+-----------------+-----------------+
| This is a value | This is a value | This is a value |
+-----------------+-----------------+-----------------+
| This is a value | This is a value | This is a value |
+-----------------+-----------------+-----------------+

在纯文本中,它实际上是这样的:

Column One,Column Two,Column Three
This is a value,This is a value,This is a value
This is a value,This is a value,This is a value
This is a value,This is a value,This is a value

我的 spark.read 方法如下所示:

val df = spark.read
    .format("csv")
    .schema(schema)
    .option("quote", "\"")
    .option("escape", "\"")
    .option("header", "true")
    .option("multiLine", "true")
    .option("mode", "DROPMALFORMED")
    .load(inputFilePath)

multiLine 设置为 true 时,df 加载为空。当 multiLine 设置为 false 时加载正常,但我需要将 multiLine 设置为 true

如果我将 Column Three 的名称更改为 ColumnThree,并在 schema object 中更新它,则它可以正常工作。 multiLine 似乎应用于 header 行!我希望当 header 也设置为 true 时不会出现这种情况。

有什么办法解决这个问题吗?我应该使用 univocity 解析器而不是默认的 commons 吗?

更新:

我不知道为什么模拟数据运行良好。这是数据的更接近表示:

CSV(仅 1 header 和 1 行数据...):

Digital ISBN,Print ISBN,Title,Price,File Name,Description,Book Cover File Name
97803453308,test,This is English,29.99,qwe_1.txt,test,test

架构和 spark.read 方法:

val df = spark.read
  .format("csv")
  .schema(StructType(Array(
    StructField("Digital ISBN", StringType, true),
    StructField("Print ISBN", StringType, true),
    StructField("Title", StringType, true),
    StructField("File Name", StringType, true),
    StructField("Price", StringType, true),
    StructField("Description", StringType, true),
    StructField("Book Cover File Name", StringType, true)
  )))
  .option("quote", "\"")
  .option("escape", "\"")
  .option("header", "true")
  .option("multiLine", "true")
  .option("mode", "DROPMALFORMED")
  .load(inputFilePath)

df.show() 结果为 spark-shell:

+------------+----------+-----+---------+-----+-----------+--------------------+
|Digital ISBN|Print ISBN|Title|File Name|Price|Description|Book Cover File Name|
+------------+----------+-----+---------+-----+-----------+--------------------+
+------------+----------+-----+---------+-----+-----------+--------------------+

更新 2:

我想我找到了 "what's different"。当我复制 CSV 中的数据并将其保存到另一个 CSV 时,它工作正常。但是原始 CSV(由 Excel 保存)失败了……Excel 保存的 CSV 是 1290 字节,而我自己创建的 CSV(工作正常)是 1292 字节…… .

更新 3:

我在 vim 中打开了 Update2 中提到的两个文件,发现 Excel 保存的 CSV 有 ^M 而不是新行。我之前的所有测试都是有缺陷的,因为它总是比较最初由 Excel 保存的 CSV 与从 Sublime 创建的 CSV ...... Sublime 没有显示出差异。我确定我可以安装一个设置或包来查看它,因为我使用 Sublime 作为我的 go-to one-off 文件编辑器...

不确定我是否应该关闭这个问题,因为标题具有误导性。话又说回来,对外面的人来说一定有一些价值哈哈...

我在将 multiLine 选项应用于页眉时遇到了同样的问题。我通过添加忽略尾随白色 space.

的附加选项来解决它
  .option("header", true)
  .option("multiLine", true)
  .option("ignoreTrailingWhiteSpace", true)

由于这个问题有一些赞成票,这里是对原始问题的解决方案作为答案...

Windows 世界中保存的文件中的换行符同时包含 carriage returnline feed。 Spark(Linux 上的 运行)将此视为格式错误的行并将其删除,因为在它的世界中,换行符只是 line feed.

课程:

  • 熟悉您正在使用的文件的来源很重要。
  • 调试数据处理问题时,使用显示回车符的编辑器 returns。