首页 > 解决方案 > 有没有办法在 Spark(使用 Scala)中通过自定义分隔符拆分而不是逐行读取,以读取一组键、值对?

问题描述

我有一个格式的输入 .txt 文件。

Record  
ID||1  
Word||ABC   
Language||English   
Count||2   
Record  
ID||2  
Word||DEF  
Language||French  
Count||4 

等等。

我是 Apache Spark/Scala 的新手。

我看到有使用 .textFile 方法逐行读取文件或使用 .wholeTextFile 方法读取整个文件的选项。我们还可以读取 CSV 格式的文件。

但是假设我想读取这样一个文件并从中创建一个案例类,其中包含成员 id、word、language、count,我该怎么做呢?

标签: scalaapache-sparkapache-spark-sql

解决方案


假设您的输入格式是一致的(没有随机空格,始终以“Record\n”结尾),以下代码有效。

关键在于hadoop配置的"textinputformat.record.delimiter"

case class Foo(ID : Long, Word : String, Language : String, Count : Long)

.

val conf = new SparkConf()
conf.setMaster("local[*]")
conf.setAppName("stackOverflow")
val sc = new SparkContext(conf)

sc.hadoopConfiguration.set("textinputformat.record.delimiter","Record\n")

val rdd = sc.textFile("C:\\TEMP\\stack.txt")
  .flatMap(record => {
    if (record.isEmpty) None //needed to remove first empty string delimited by "Record\n"
    else {
      val lines = record.split("\n").map(_.split("\\|\\|"))
      //lines.foreach(x=>println(x.mkString(",")))
      Some(Foo(
        lines(0)(1).toLong,
        lines(1)(1),
        lines(2)(1),
        lines(3)(1).toLong
      ))
    }
  })
rdd.foreach(println)

输出是

Foo(2,DEF,French,4)
Foo(1,ABC,English,2)

推荐阅读