Spark CSV包无法在字段内处理\ n

时间:2017-05-30 17:17:51

标签: scala apache-spark apache-spark-sql spark-csv apache-spark-1.6

我有一个CSV文件,我尝试使用Spark CSV package加载它并且它无法正确加载数据,因为其中很少有字段包含if ($user->has('followed')) { foreach ($user->followed as $followed) { debug($followed->username); } } ,例如以下两行

\n

我正在使用以下代码,这是直截了当的我使用"XYZ", "Test Data", "TestNew\nline", "OtherData" "XYZ", "Test Data", "blablablabla \nblablablablablalbal", "OtherData" 作为parserLib在互联网上阅读它解决了多个换行问题,但对我来说似乎不是这样。

univocity

请指导如何在以引号开头的字段中替换换行符。有没有更简单的方法?

3 个答案:

答案 0 :(得分:3)

根据SPARK-14194(已解决为重复),不支持使用新行字符的字段,且不会支持。

  

我建议通过wholeFile选项解决此问题,它似乎已合并。我正在解决这个问题,因为那个人有PR。

然而,Spark 2.0,你使用spark-csv模块。

在引用的SPARK-19610中,它已使用pull request修复:

  嗯,我明白了这个动机,虽然我对csv的理解通常要么避免在字段中使用换行符,要么某些实现需要使用换行符在字段值周围引用

换句话说,在Spark 2.x中使用wholeFile选项(正如您在CSVDataSource中看到的那样)。

至于spark-csv,this comment可能会有所帮助(突出我的):

  

但是,有很多类似的JIRA抱怨这个,并且原始的CSV数据源试图支持这一点,尽管这是错误的实现。这至少会尝试将其与JSON配对,最好提供一种处理此类CSV文件的方法。 实际上,当前的实现需要引号 :)。 (有人告诉R实际上支持这个案例)。

在spark-csv' Features中,您可以找到以下内容:

  

该软件包还支持保存简单(非嵌套)DataFrame。在编写文件时,API接受以下几个选项:

     
      
  • 引用:默认情况下,引号字符为",但可以设置为任何字符。这是根据quoteMode撰写的。

  •   
  • quoteMode :何时引用字段(ALL,MINIMAL(默认),NON_NUMERIC,NONE),请参阅引用模式

  •   

答案 1 :(得分:2)

Spark 2.2的用户可以选择考虑CSV文件中的换行符。它最初被讨论为被称为wholeFile但在发布之前被重命名为multiLine

以下是使用该选项将CSV加载到数据框的示例:

var webtrends_data = (sparkSession.read
.option("header", "true")
.option("inferSchema", "true")
.option("multiLine", true)
.option("delimiter", ",")
.format("csv")
.load("hdfs://hadoop-master:9000/datasource/myfile.csv"))

答案 2 :(得分:0)

升级到Spark 2.x.换行符实际上是由ascii 13和10表示的CRLF。但反斜杠和' n'是不同的ascii,以编程方式解释和书写。 Spark 2.x将正确读取..我试过它.s.b。
val conf = new SparkConf().setAppName("HelloSpark").setMaster("local[2]") val sc = SparkSession.builder().master("local").getOrCreate() val df = sc.read.csv("src/main/resources/data.csv") df.foreach(row => println(row.mkString(", ")))
如果你不能升级,那么用正则表达式清理RDD上的\ n。这不会删除行尾,因为它是$ in regex。 S.B.

  val conf = new SparkConf().setAppName("HelloSpark").setMaster("local")
  val sc = new SparkContext(conf)
  val rdd1 = sc.textFile("src/main/resources/data.csv")
  val rdd2 = rdd1.map(row => row.replace("\\n", ""))
  val sqlContext = new SQLContext(sc)

  import sqlContext.implicits._
  val df = rdd2.toDF()
  df.foreach(row => println(row.mkString(", ")))