Spark Context Textfile:加载多个文件

时间:2014-04-30 21:00:17

标签: python apache-spark

我需要处理分散在各个目录中的多个文件。我想在一个RDD中加载所有这些,然后对它执行map / reduce。我看到SparkContext能够使用通配符从单个目录加载多个文件。我不知道如何从多个文件夹中加载文件。

以下代码段失败:

for fileEntry in files:
    fileName = basePath + "/" + fileEntry
    lines = sc.textFile(fileName)
    if retval == None:
        retval = lines
    else:
        retval = sc.union(retval, lines)

第三次循环失败,出现以下错误消息:

retval = sc.union(retval, lines)
TypeError: union() takes exactly 2 arguments (3 given)

鉴于我只提供了2个参数,这是奇怪的。任何指针都赞赏。

4 个答案:

答案 0 :(得分:42)

这句话怎么样?

sc.union([sc.textFile(basepath + "/" + f) for f in files])

在Scala SparkContext.union()中有两个变体,一个采用vararg参数,另一个采用列表。只有第二个存在于Python中(因为Python没有多态性)。

更新

您可以使用单个textFile调用来读取多个文件。

sc.textFile(','.join(files))

答案 1 :(得分:13)

我使用通配符解决了类似的问题。

e.g。我在要加载的文件中找到了一些特性,

  

DIR

     
    

subdir1 / folder1中/ x.txt

         

subdir2 /文件夹2 / y.txt

  

您可以使用以下句子

sc.textFile("dir/*/*/*.txt")

加载所有相关文件。

通配符' *'仅适用于单级目录,这不是递归的。

答案 2 :(得分:2)

您可以使用SparkContext的以下功能:

wholeTextFiles(path: String, minPartitions: Int = defaultMinPartitions): RDD[(String, String)]

从HDFS读取文本文件目录,本地文件系统(在所有节点上都可用)或任何Hadoop支持的文件系统URI。每个文件都作为单个记录读取,并以键值对的形式返回,其中键是每个文件的路径,值是每个文件的内容。

https://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.SparkContext

答案 3 :(得分:1)

您可以使用此

首先,您可以获得S3路径的缓冲区/列表:

import scala.collection.JavaConverters._
import java.util.ArrayList
import com.amazonaws.services.s3.AmazonS3Client
import com.amazonaws.services.s3.model.ObjectListing
import com.amazonaws.services.s3.model.S3ObjectSummary
import com.amazonaws.services.s3.model.ListObjectsRequest

def listFiles(s3_bucket:String, base_prefix : String) = {
    var files = new ArrayList[String]

    //S3 Client and List Object Request
    var s3Client = new AmazonS3Client();
    var objectListing: ObjectListing = null;
    var listObjectsRequest = new ListObjectsRequest();

    //Your S3 Bucket
    listObjectsRequest.setBucketName(s3_bucket)

    //Your Folder path or Prefix
    listObjectsRequest.setPrefix(base_prefix)

    //Adding s3:// to the paths and adding to a list
    do {
      objectListing = s3Client.listObjects(listObjectsRequest);
      for (objectSummary <- objectListing.getObjectSummaries().asScala) {
        files.add("s3://" + s3_bucket + "/" + objectSummary.getKey());
      }
      listObjectsRequest.setMarker(objectListing.getNextMarker());
    } while (objectListing.isTruncated());

    //Removing Base Directory Name
    files.remove(0)

    //Creating a Scala List for same
    files.asScala
  }

现在将此List对象传递给以下代码段,注意:sc是SQLContext的对象

var df: DataFrame = null;
  for (file <- files) {
    val fileDf= sc.textFile(file)
    if (df!= null) {
      df= df.unionAll(fileDf)
    } else {
      df= fileDf
    }
  }

现在你有一个最终的统一RDD,即df

可选,您也可以在一个BigRDD

中重新分区
val files = sc.textFile(filename, 1).repartition(1)

重新分区始终有效:D

相关问题