【问题标题】:Spark-Csv Write quotemode not workingSpark-Csv写报价模式不起作用
【发布时间】:2016-09-03 10:48:50
【问题描述】:

我正在尝试使用 Spark-CSV (https://github.com/databricks/spark-csv) 将 DataFrame 编写为 CSV 文件

我正在使用下面的命令

res1.write.option("quoteMode", "NONE").format("com.databricks.spark.csv").save("File")

但我的 CSV 文件总是写成

“伦敦”
“哥本哈根”
“莫斯科”

而不是

伦敦
哥本哈根
莫斯科

【问题讨论】:

标签: apache-spark apache-spark-sql spark-dataframe


【解决方案1】:

这个问题困扰了我很长时间,直到我读到这个:Adding custom Delimiter adds double quotes in the final spark data frame CSV outpu

这是一个标准的 CSV 功能。如果实际数据中出现分隔符(称为分隔符冲突),则该字段用引号引起来。 你可以试试 df.write.option("分隔符" , somechar) 其中 somechar 应该是您的数据中不存在的字符。

您可以将多列合并为一列并使用不在数据中的分隔符

【讨论】:

    【解决方案2】:

    是的。使用反斜杠字符 (\) 关闭双引号字符 (") 的默认转义的方法,您必须在 .write() 方法调用之后添加一个带有正确参数的 .option() 方法调用。目标option() 方法调用是更改 csv() 方法“查找”“引用”字符的实例的方式。为此,您必须更改“引用”实际含义的默认值;即更改查找的字符从双引号字符 (") 到 Unicode "\u0000" 字符(本质上提供Unicode NUL character,这在格式良好的 JSON 文档中永远不会出现)。

    val dataFrame =
      spark.sql("SELECT * FROM some_table_with_a_json_column")
    val unitEmitCsv =
      dataframe
        .write
        .option("header", true)
        .option("delimiter", "\t")
        .option("quote", "\u0000") //magic is happening here
        .csv("/FileStore/temp.tsv")
    

    这只是我尝试使用 Apache Spark 并发出 .csv 文件时学到的几课之一。有关这方面的更多信息和上下文,请参阅我写的标题为“Example Apache Spark ETL Pipeline Integrating a SaaS”的博文。

    【讨论】:

    • 如果是 csv 怎么办?它在文件中写入特殊字符 \u00。
    • 我刚刚在我使用制表符(不是逗号)作为列分隔符的显式行中添加了。我不确定这是否能帮助您了解您需要在我的解决方案中看到的内容。
    • 是的!它可以使用制表符作为分隔符,但不能使用。
    • 我在\u0000 上收到一条错误消息,提示“java.lang.RuntimeException: quote cannot be more than one character”你知道这是什么意思吗?
    • @chaotic3quilibrium 你拯救了我的一天。在付出了很多努力来完成任务之后,它在写入 csv 时不起作用。谢谢你让我知道“魔法”
    【解决方案3】:

    使用选项

    .option("emptyValue", "")
    

    这是火花2.4+

    【讨论】:

    • 它适用于我的管道分隔符,谢谢
    【解决方案4】:

    可以通过将quoteAll 选项设置为false 来删除文本的双引号

    dataframe.write
     .option("quoteAll", "false")
     .format("csv")
    

    这个例子是按照 Spark 2.1.0 的,没有使用 databricks 库。

    【讨论】:

    • 不适合我,双引号还在。
    • 对我也不起作用。顺便说一句,一个错字应该是option,而不是options
    • 这帮助我从空字符串中删除引号,谢谢
    【解决方案5】:

    如果你的 DataFrame 有一个字符串,你可以直接写出一个文本文件。

    df.coalesce(1).map({ k:Row => k(0).toString}).toJavaRDD.saveAsTextFile("File")
    

    如果您有多个列,您可以在写入输出文件之前将它们组合为一个字符串。

    给出的其他答案可能会导致在您的输出文件中发出不需要的空字符或空格字符。

    【讨论】:

    • 这是唯一适用于我的用例的东西,其中我必须编写一个 csv,每行都是多行字符串,不需要 spark 放入的双引号。
    • 这适用于单列项目。谢谢
    【解决方案6】:

    我可以通过将引号选项设置为单个空格来关闭它

    df.coalesce(1).write.format("com.databricks.spark.csv").option("header", "true").option("quote"," ").option("codec", "org.apache.hadoop.io.compress.GzipCodec").save("File path")
    

    但这只会替换将空格代替引号(“)的选项

    还有一个选项,即当分隔符和分隔符相同时,引号通常作为限定符来分隔某些列

    这样您就可以更改分隔符并自动删除引号

    df.coalesce(1).write.format("com.databricks.spark.csv").option("header", "true").option("delimiter", "|").option("codec", "org.apache.hadoop.io.compress.GzipCodec").save("File path")
    

    希望这适用于您的情况

    【讨论】:

    • 都不适合我。有关更多讨论,请参阅github.com/databricks/spark-csv/issues/291,但目前还没有解决方案。
    • 您的答案实际上不仅不正确,还会导致 JSON 内容损坏。因此,虽然它可能解决了您在执行此操作时遇到的一个非常具体的问题,但它并不是一个通用的解决方案。我想出了一个通用的解决方案,我自己回答这个问题:stackoverflow.com/a/43129783/501113
    【解决方案7】:

    有一些类似的情况我曾经很困惑,最后我发现一个sep参数可以改变结果,你可以试试这个:

    df.write.mode("overwrite").option("sep","\t").csv(path)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-30
      • 1970-01-01
      • 1970-01-01
      • 2014-09-20
      • 1970-01-01
      • 2021-04-14
      • 1970-01-01
      相关资源
      最近更新 更多