循环遍历文件行并通过Spark中的每次迭代执行函数

时间:2017-11-03 21:34:05

标签: scala hadoop apache-spark hdfs

我在HDFS中有一个名为file1的文件,其中包含以下行:(每行是一个目录路径)

this/is/path1
this/is/path2
this/is/path3
.
.
.
this/is/path1000ormore

我有一个Scala Spark功能如下:

val resultset=sc.hadoopFile(inputpath,classOf[TextInputFormat],classOf[LongWritable],classOf[Text]).flatMap {
case (k, v) => if (k.get == 0) Seq(v.toString) else Seq.empty[String]
}

我想传递来自" file1"的每一行。代替"输入路径" (必须是一个String)在hadoopFile函数中,并获得每个迭代/循环的结果。 我怎么能这样做?

额外信息:

函数实际执行的操作:上面的函数从指定的目录路径获取第一个文件,而不是" inputpath"并给出文件的第一行。我想对存储在" file1"中的所有目录路径执行此操作,因此我正在寻找有关如何在循环/迭代中执行此操作的解决方案。

更新 我试着将它放在这样的循环中:

val lines=Source.fromFile("/path/to/file1.txt").getLines.toList
for(i<-lines){
val firstLines=sc.hadoopFile(i,classOf[TextInputFormat],classOf[LongWritable],classOf[Text]).flatMap {
case (k, v) => if (k.get == 0) Seq(v.toString) else Seq.empty[String]
}

这大约持续了10分钟(file1包含大约34,000行)并且没有导致任何错误。但是当我尝试使用以下命令查看输出的几行时,

firstLines.take(3)

我收到错误说:

error: not found: value firstLines
          firstLines
          ^

所以我不认为循环成功运行,因此firstLines永远不会被创建,尽管我不知道问题是什么。有人可以提供解决方案吗?

1 个答案:

答案 0 :(得分:1)

可以分两步完成:

  1. 从HDFS读取“file1”作为通常的文本文件,获取所有元素;
  2. 对于1)中的每个项目,应用“结果集”逻辑。
  3. 另外2)可以改进:1)中的所有项目都可以用逗号连接在一个字符串中,字符串作为“inputpath”参数传递。您将拥有一个包含所有文件数据的RDD。可以应用过滤器“k.get == 0”来获得最终结果。

    首先可以这样实现:

    val lines = Source.fromFile("file1.txt").getLines.toSeq.view
    
    val resultDF = lines.map(current =>
      sc.hadoopFile(current, classOf[TextInputFormat], classOf[LongWritable], classOf[Text]).filter(_._1 == 0)
    ).reduce(_ union _)
    
    resultDF.take(3).foreach(println)