为什么Spark textFile方法不读取整个文本文件?

时间:2015-05-26 19:02:42

标签: scala apache-spark

class Cleaner {
  def getDocumentData() = {
    val conf = new SparkConf()
      .setAppName("linkin_spark")
      .setMaster("local[2]")
      .set("spark.executor.memory", "1g")
      .set("spark.rdd.compress", "true")
      .set("spark.storage.memoryFraction", "1")

    val CorpusReader = new Corpus()
    val files = CorpusReader.getListOfFiles("/home/DATA/doc_collection/")

    val sc = new SparkContext(conf)
    val temp = sc.textFile(files(0).toString())
    println(files(0).toString())

    var count = 0
    val regex = """<TAG>""".r
    for (line <- temp ) {
      line match {
        case regex(_*) => {
          println(line)
          count += 1
          println(count)
        }
        case _ => null //Handle error - scala.MatchError
      }
    }
    println(s"There are " + count + " documents.") // this comes out to be 0
  }
}

我有一个我必须阅读的文本文件列表。它们是类似XML的文件,所以我需要提取相关的文本。因为,它们不是标准的XML文件,我想用正则表达式来获取文本。每个文档都以<TAG>标记开头。所以我试着算不了。文件中的文件等于否。 <TAG>匹配文件中的匹配项。上面的功能做了同样的事情。最初该文件有264个文档但是当我运行该函数时,我得到127或137,这两个数字。它似乎没有读取整个文件。最后count最后也是0.

我是Scala / Spark新手。

更新

var count = sc.accumulator(0)
val regex = """<TAG>""".r
for (line <- temp ) {
  println(line)
  line match {
    case regex(_*) => {
      count += 1
      println(s"$line @ $count")      //There is no "<TAG> @ 264" in the output
    }
    case _ => null
  }
}
println(s"There are " + count.value + " documents.")

程序中的这一更改为我提供了count的正确值,即264,但文件ID正确打印!!它似乎从中间开始,到中间的某个地方结束。

更新II:

这与线程有关。 SparkConf()已经使用local[2]初始化,这意味着2个线程,如果我没有错的话。一旦我将其更改为local[1],我得到了正确的答案,但我不能使用一个帖子。

文件如下所示:

<TAG>
<DOCNO> AP890825-0001 </DOCNO>
<FILEID>AP-NR-08-25-89 0134EDT</FILEID>
<TEXT>
Some large text.
</TEXT>
</TAG>
<TAG> // new doc started

我该如何纠正这个问题?

1 个答案:

答案 0 :(得分:2)

这是一个关闭问题。每个节点都有自己的count变量版本。您想使用accumulators或只是执行reduce

创建者:

val tagCounter = sc.accumulator(0, "tagCount")

更新者:(节点上无法读取)

tagCounter += 1

可通过以下方式阅读驱动程序:

tagCounter.value

更新后:

var count = sc.accumulator(0)
val regex = """<TAG>""".r
val output = for (line <- temp ) yield {
  //println(line)
  line match {
    case regex(_*) => {
      count += 1
      //println(s"$line @ $count")      //There is no "<TAG> @ 264" in the output
      line
    }
    case _ => "ERROR"
  }
}
println(s"output size:{output.count}")
println(s"There are " + count.value + " documents.")

查看输入格式后的更新:

您最终会随心所欲地使用wholeTextFiles来保证订购。否则分布式性质意味着通常无法保证订购,但如果您可以保证订购(可能是自定义分区程序或自定义InputFormat),那么这样的事情应该有效:

sc.parallelize(list)
  .aggregate(Nil : List[String])((accum, value) => {
    value match {
      case regex(_*) => accum :+ value
      case _ => {
        accum match {
          case Nil => List(value)
          case _ => accum.init ++ (accum.tail :+ value)
      }
    }
  }, _ ++ _)