spark 2.0用json读取csv

时间:2017-11-08 09:31:26

标签: scala csv apache-spark

我的CSV文件如下:

"a","b","c","{""x"":""xx"",""y"":""yy""}"

当我使用java CSV阅读器(au.com.bytecode.opencsv.CSVParser)时,它会在我指示defaultEscapeChar = '\u0000'

时设法解析字符串

当我尝试使用spark 2.2 CSV阅读器阅读时,它失败了,无法将其拆分为4列。这就是我试过的:

val df = spark.read.format("csv")
              .option("quoteMode","ALL")
              .option("quote", "\u0000")
              .load("s3://...")

我也尝试option("escape", "\u0000") 但没有运气。

我需要选择哪些CSV选项才能正确解析此文件?

2 个答案:

答案 0 :(得分:2)

你实际上很接近,正确的选项是option("escape", "\"") 所以考虑到最近的火花版本(2.2+或甚至更早),下面的片段

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

object CsvJsonMain {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder().appName("CsvJsonExample").master("local").getOrCreate()

    import spark.sqlContext.implicits._
    val csvData: Dataset[String] = spark.sparkContext.parallelize(List(
      """
        |"a","b","c","{""x"":""xx"",""y"":""yy""}"
      """.stripMargin)).toDS()

    val frame = spark.read.option("escape", "\"").csv(csvData)
    frame.show()
  }
}

会产生

+---+---+---+-------------------+
|_c0|_c1|_c2|                _c3|
+---+---+---+-------------------+
|  a|  b|  c|{"x":"xx","y":"yy"}|
+---+---+---+-------------------+

spark无法解析这样的csv开箱即用的原因是默认的转义值是' \'在CSVOptions的第91行可以看到符号,它显然无法使用默认的json引号转义。

它曾经在使用databricks-csv库的spark 2.0之前工作的根本原因是底层的csv引擎曾经是commons-csv并且转义字符默认为null将允许库检测json及其#s; s逃避的方式。由于2.0 csv功能是火花本身的一部分,并且使用uniVocity CSV parser并没有提供这样的"魔法"但显然速度更快。

P.S。如果要保留json数据,请不要忘记在编写csv文件时指定转义。

frame.write.option("quoteAll","true").option("escape", "\"").csv("csvFileName") 

答案 1 :(得分:-1)

我在Spark 1.6上使用Spark CSV作为外部JAR,但这对我有用:

sqlContext.read.format("com.databricks.spark.csv")
          .option("quoteMode", "ALL")
          .option("delimiter", ",")
          .load("file")
          .show

+---+---+---+-------------------+
| C0| C1| C2|                 C3|
+---+---+---+-------------------+
|  a|  b|  c|{"x":"xx","y":"yy"}|
+---+---+---+-------------------+

编辑:看起来Spark CSV足够智能

sc.textFile("file").collect
res7: Array[String] = Array(a,b,c,"{""x"":""xx"",""y"":""yy""}")

scala> sqlContext.read.format("com.databricks.spark.csv").load("file").show
+---+---+---+-------------------+
| C0| C1| C2|                 C3|
+---+---+---+-------------------+
|  a|  b|  c|{"x":"xx","y":"yy"}|
+---+---+---+-------------------+


scala> sqlContext.read.format("com.databricks.spark.csv").option("quoteMode", "ALL").load("file").show
+---+---+---+-------------------+
| C0| C1| C2|                 C3|
+---+---+---+-------------------+
|  a|  b|  c|{"x":"xx","y":"yy"}|
+---+---+---+-------------------+