如何在Apache Spark中读取包含多个文件的zip

时间:2015-08-18 18:52:41

标签: scala apache-spark pyspark

我有一个包含多个文本文件的Zipped文件。 我想阅读每个文件并构建一个包含每个文件内容的RDD列表。

val test = sc.textFile("/Volumes/work/data/kaggle/dato/test/5.zip")

将只是整个文件,但如何遍历zip的每个内容,然后使用Spark将其保存在RDD中。

我对Scala或Python很好。

Python中使用Spark的可能解决方案 -

archive = zipfile.ZipFile(archive_path, 'r')
file_paths = zipfile.ZipFile.namelist(archive)
for file_path in file_paths:
    urls = file_path.split("/")
    urlId = urls[-1].split('_')[0]

5 个答案:

答案 0 :(得分:7)

Apache Spark默认压缩支持

我在其他答案中写了所有必要的理论,你可能想参考:https://stackoverflow.com/a/45958182/1549135

读取包含多个文件的zip

我已按照 @Herman 提供的建议并使用了ZipInputStream。这给了我这个解决方案,它返回了RDD[String]的zip内容。

import java.io.{BufferedReader, InputStreamReader}
import java.util.zip.ZipInputStream
import org.apache.spark.SparkContext
import org.apache.spark.input.PortableDataStream
import org.apache.spark.rdd.RDD

implicit class ZipSparkContext(val sc: SparkContext) extends AnyVal {

    def readFile(path: String,
                 minPartitions: Int = sc.defaultMinPartitions): RDD[String] = {

      if (path.endsWith(".zip")) {
        sc.binaryFiles(path, minPartitions)
          .flatMap { case (name: String, content: PortableDataStream) =>
            val zis = new ZipInputStream(content.open)
            Stream.continually(zis.getNextEntry)
                  .takeWhile {
                      case null => zis.close(); false
                      case _ => true
                  }
                  .flatMap { _ =>
                      val br = new BufferedReader(new InputStreamReader(zis))
                      Stream.continually(br.readLine()).takeWhile(_ != null)
                  }
        }
      } else {
        sc.textFile(path, minPartitions)
      }
    }
  }

只需通过导入隐式类并在SparkContext上调用readFile方法来使用它:

import com.github.atais.spark.Implicits.ZipSparkContext
sc.readFile(path)

答案 1 :(得分:4)

如果您正在阅读二进制文件,请使用sc.binaryFiles。这将返回包含文件名和PortableDataStream的元组的RDD。您可以将后者提供给ZipInputStream

答案 2 :(得分:1)

这是@Atais解决方案的工作版本(需要通过关闭流来增强其功能):

implicit class ZipSparkContext(val sc: SparkContext) extends AnyVal {

def readFile(path: String,
             minPartitions: Int = sc.defaultMinPartitions): RDD[String] = {

  if (path.toLowerCase.contains("zip")) {

    sc.binaryFiles(path, minPartitions)
      .flatMap {
        case (zipFilePath, zipContent) ⇒
          val zipInputStream = new ZipInputStream(zipContent.open())
          Stream.continually(zipInputStream.getNextEntry)
            .takeWhile(_ != null)
            .map { _ ⇒
              scala.io.Source.fromInputStream(zipInputStream, "UTF-8").getLines.mkString("\n")
            } #::: { zipInputStream.close; Stream.empty[String] }
      }
  } else {
    sc.textFile(path, minPartitions)
  }
}
}

然后您要做的就是读取zip文件:

sc.readFile(path)

答案 3 :(得分:1)

这仅过滤第一行。任何人都可以分享您的见解。我正在尝试读取已压缩的CSV文件,并创建JavaRDD进行进一步处理。

create table all_index_points(
id varchar(450) NOT NULL PRIMARY KEY,
latitude float,
longitude float,
streetname nvarchar(MAX),
longlat geography
);

答案 4 :(得分:-1)

这是另一个可行的解决方案,它给出文件名,该文件名以后可以拆分并用于从中创建单独的模式。

implicit class ZipSparkContext(val sc: SparkContext) extends AnyVal {

    def readFile(path: String,
                 minPartitions: Int = sc.defaultMinPartitions): RDD[String] = {

      if (path.toLowerCase.contains("zip")) {

        sc.binaryFiles(path, minPartitions)
          .flatMap {
            case (zipFilePath, zipContent) ⇒
              val zipInputStream = new ZipInputStream(zipContent.open())
              Stream.continually(zipInputStream.getNextEntry)
                .takeWhile(_ != null)
                .map { x ⇒
                  val filename1 = x.getName
                  scala.io.Source.fromInputStream(zipInputStream, "UTF-8").getLines.mkString(s"~${filename1}\n")+s"~${filename1}"
                } #::: { zipInputStream.close; Stream.empty[String] }
          }
      } else {
        sc.textFile(path, minPartitions)
      }
    }
  }

完整代码在这里

https://github.com/kali786516/Spark2StructuredStreaming/blob/master/src/main/scala/com/dataframe/extraDFExamples/SparkReadZipFiles.scala