2017-06-04 48 views
0

我寫了一個簡單的代碼來解析一個大的XML文件(提取行,乾淨的文本,並從它刪除任何HTML標記)使用Apache Spark。在簡單的正則表達式取代NPE

對字符串調用.replaceAllIn時,我看到一個NullPointerException,該字符串非空。

有趣的是,我沒有錯誤,當我在本地運行代碼,使用從磁盤輸入,但我得到一個NullPointerException當我運行在AWS EMR相同的代碼,加載從S3輸入文件。

下面是相關代碼:

val HTML_TAGS_PATTERN = """<[^>]+>""".r 

// other code here... 

spark 
.sparkContext 
.textFile(pathToInputFile, numPartitions) 
.filter { str => str.startsWith(" <row ") } 
.toDS() 
.map { str => 

    Locale.setDefault(new Locale("en", "US")) 

    val parts = str.split(""""""") 

    var title: String = "" 
    var body: String = "" 

    // some code ommitted here 

    title = StringEscapeUtils.unescapeXml(title).toLowerCase.trim 
    body = StringEscapeUtils.unescapeXml(body).toLowerCase // decode xml entities 


    println("before replacing, body is: "+body) 

    // NEXT LINE TRIGGERS NPE 
    body = HTML_TAGS_PATTERN.replaceAllIn(body, " ") // take out htmltags 

} 

事情我已經嘗試:

  • 打印字符串只是打電話replaceAllIn,以確保它不是null之前。

  • 確保區域設置不爲空

  • 打印出異常信息,並堆棧跟蹤:它只是告訴我,這條線是其中的NullPointerException發生。沒有更多

的事情,是我的本地設置和AWS EMR之間的不同:在我的本地設置

  • ,我從磁盤加載輸入文件,對EMR我從S3加載它。

  • 在我的本地設置中,我以獨立模式運行Spark,在集羣模式下運行EMR。


其他的都是我的機器上和AWS EMR是相同的:Scala的版本,星火版本,Java版本,集羣CONFIGS ...

我一直在試圖弄清楚這一點對幾個小時,我想不出別的辦法。

編輯

我搬到調用r()map{}體內,就像這樣:

val HTML_TAGS_PATTERN = """<[^>]+>""" 

// code ommited 

.map{ 

    body = HTML_TAGS_PATTERN.r.replaceAllIn(body, " ")  

} 

這也產生了NPE,機智以下stracktrace:

java.lang.NullPointerException 
    at java.util.regex.Pattern.<init>(Pattern.java:1350) 
    at java.util.regex.Pattern.compile(Pattern.java:1028) 
    at scala.util.matching.Regex.<init>(Regex.scala:191) 
    at scala.collection.immutable.StringLike$class.r(StringLike.scala:255) 
    at scala.collection.immutable.StringOps.r(StringOps.scala:29) 
    at scala.collection.immutable.StringLike$class.r(StringLike.scala:244) 
    at scala.collection.immutable.StringOps.r(StringOps.scala:29) 
    at ReadSOStanfordTokenize$$anonfun$2.apply(ReadSOStanfordTokenize.scala:102) 
    at ReadSOStanfordTokenize$$anonfun$2.apply(ReadSOStanfordTokenize.scala:72) 
    at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIterator.processNext(Unknown Source) 
    at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43) 
    at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$8$$anon$1.hasNext(WholeStageCodegenExec.scala:377) 
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$SingleDirectoryWriteTask.execute(FileFormatWriter.scala:243) 
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$org$apache$spark$sql$execution$datasources$FileFormatWriter$$executeTask$3.apply(FileFormatWriter.scala:190) 
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$org$apache$spar 
+1

你試過把正則表達式內聯嗎?它是null的正則表達式而不是字符串主體。這可能是正則表達式Isnt正確地分發給工人。你可以包含一些堆棧跟蹤嗎? – Stephen

+0

@Stephen我試着在'map {}內調用'.r()',現在這就是stacktrace的樣子:[gist link here](https://gist.github.com/queirozfcom/) 0aece2c4912017f0941a78a03de97fe9)(它看起來好像和正則表達式有關) –

+0

@Stephen我現在把整個String聲明放到worker代碼中,它看起來像是一個win .... =)....寫出來一個答案,所以我可以打你綠色。 =) –

回答

1

我認爲你應該嘗試把內聯正如波紋管一樣。

這是一個蹩腳的解決方案,你應該能夠定義一個常量,也許把它放在全局的object什麼的。林不知道你在哪裏定義它,這將是一個問題。但是請記住,spark會將代碼串行化並在分佈式工作器上運行,所以可能會出現問題。

rdd.map { _ => 
    ... 

    body = """<[^>]+>""".r.replaceAllIn(body, " ")  

} 

當我在空字符串上運行.r時,出現非常類似的錯誤。

val x: String = null 
x.r 
java.lang.NullPointerException 
    java.util.regex.Pattern.<init>(Pattern.java:1350) 
    java.util.regex.Pattern.compile(Pattern.java:1028) 
    scala.util.matching.Regex.<init>(Regex.scala:223) 
    scala.collection.immutable.StringLike.r(StringLike.scala:281) 
    scala.collection.immutable.StringLike.r$(StringLike.scala:281) 
    scala.collection.immutable.StringOps.r(StringOps.scala:29) 
    scala.collection.immutable.StringLike.r(StringLike.scala:270) 
    scala.collection.immutable.StringLike.r$(StringLike.scala:270) 
    scala.collection.immutable.StringOps.r(StringOps.scala:29) 

該錯誤有一些不同的行號,我認爲是因爲scala版本。我在2.12.2。

+0

太棒了! !有效! –

+0

順便說一句,你有什麼想法,爲什麼一個簡單的字符串不能傳遞到地圖塊?這看起來很基本。 –

+1

它不是因爲它是一個String或一個正則表達式。它與該字符串所在的位置有關。例如,在一個對象或嵌套在某個東西中的匿名類。林不知道,也許看看如何火花序列化代碼。 – Stephen