Compression apachespark中的Zip支持

Compression apachespark中的Zip支持,compression,zip,apache-spark,Compression,Zip,Apache Spark,我读过Spark对gzip类输入文件的支持,我想知道对不同类型的压缩文件(如.zip文件)是否也有相同的支持。到目前为止,我已经尝试过计算压缩在zip文件下的文件,但Spark似乎无法成功读取其内容 我已经看了Hadoop的newapiHadoop文件和newAPIHadoopRDD,但到目前为止,我还不能让任何东西正常工作 此外,Spark支持为指定文件夹下的每个文件创建分区,如下例所示: SparkConf SpkCnf = new SparkConf().setAppName("Spark

我读过Spark对gzip类输入文件的支持,我想知道对不同类型的压缩文件(如.zip文件)是否也有相同的支持。到目前为止,我已经尝试过计算压缩在zip文件下的文件,但Spark似乎无法成功读取其内容

我已经看了Hadoop的
newapiHadoop文件
newAPIHadoopRDD
,但到目前为止,我还不能让任何东西正常工作

此外,Spark支持为指定文件夹下的每个文件创建分区,如下例所示:

SparkConf SpkCnf = new SparkConf().setAppName("SparkApp")
                                  .setMaster("local[4]");

JavaSparkContext Ctx = new JavaSparkContext(SpkCnf);

JavaRDD<String> FirstRDD = Ctx.textFile("C:\input\).cache();
SparkConf SpkCnf=new SparkConf().setAppName(“SparkApp”)
.setMaster(“本地[4]”;
JavaSparkContext Ctx=新的JavaSparkContext(SpkCnf);
JavaRDD FirstRDD=Ctx.textFile(“C:\input\).cache();
其中
C:\input\
指向包含多个文件的目录


如果可以计算压缩文件,是否也可以将每个文件打包到一个压缩文件下,并遵循每个文件一个分区的相同模式?

由于ApacheSpark使用Hadoop输入格式,我们可以查看Hadoop文档中关于如何处理压缩文件的内容,看看是否有可行的方法。

让我们了解如何使用它(即我们可以使用ZipFileInputFormat)。也就是说,由于zip文件不是拆分表(请参阅),因此并不真正支持使用单个压缩文件的请求。相反,如果可能的话,最好有一个包含多个单独zip文件的目录


这个问题与类似,但它增加了一个额外的问题,即是否可以使用单个zip文件(因为它不是拆分表格式,所以这不是一个好主意)。

您可以使用sc.binaryFiles将zip作为二进制文件读取

val rdd = sc.binaryFiles(path).flatMap { 
    case (name: String, content: PortableDataStream) => new ZipInputStream(content.open) 
}  //=> RDD[ZipInputStream]
然后您可以将ZipInputStream映射到行列表:

val zis = rdd.first
val entry = zis.getNextEntry
val br = new BufferedReader(new InputStreamReader(in, "UTF-8"))
val res = Stream.continually(br.readLine()).takeWhile(_ != null).toList

但问题仍然是zip文件不可拆分。

您可以使用sc.binaryFiles以二进制格式打开zip文件,然后将其解压缩为文本格式。不幸的是,zip文件无法拆分。因此您需要等待解压,然后调用shuffle来平衡每个分区中的数据

下面是Python中的一个示例


下面是一个在Spark上下文中搜索.zip文件目录并使用名为
ZipFileInputFormat
的自定义FileInputFormat和newAPIHadoopFile API创建RDD的示例。然后将这些文件写入输出目录

allzip.foreach { x =>
  val zipFileRDD = sc.newAPIHadoopFile(
    x.getPath.toString,
    classOf[ZipFileInputFormat],
    classOf[Text],
    classOf[BytesWritable], hadoopConf)

  zipFileRDD.foreach { y =>
    ProcessFile(y._1.toString, y._2)
  }

示例中使用的ZipFileInputFormat可在此处找到:

Spark默认支持压缩文件 据

Spark所有基于文件的输入方法,包括textFile,都支持在目录、压缩文件和通配符上运行。例如,您可以使用textFile(“/my/directory”)、textFile(“/my/directory/.txt”)和textFile(“/my/directory/.gz”)

这可以通过提供关于Hadoop支持哪些压缩格式的信息来扩展,基本上可以通过查找所有扩展
CompressionCodec
()

资料来源:

因此,只需调用以下命令即可实现上述格式和更多可能性:

sc.readFile(path)
在Spark中读取zip文件 遗憾的是,默认情况下,
zip
不在支持列表中

我找到了一篇很棒的文章:和一些答案(),解释了如何将导入的
ZipFileInputFormat
sc.newAPIHadoopFile
API一起使用。但是这个对我不起作用

我的解决方案 在没有任何外部依赖项的情况下,您可以使用
sc.binaryFiles
加载文件,然后解压缩
PortableDataStream
读取内容。这是我选择的方法

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)
            // this solution works only for single file in the zip
            val entry = zis.getNextEntry
            val br = new BufferedReader(new InputStreamReader(zis))
            Stream.continually(br.readLine()).takeWhile(_ != null)
          }
      } else {
        sc.textFile(path, minPartitions)
      }
    }
  }
使用这个隐式类,您需要导入它并调用
readFile
SparkContext
上的方法:

import com.github.atais.spark.Implicits.ZipSparkContext
sc.readFile(path)
隐式类将正确加载
zip
文件,并像以前一样返回
RDD[String]

注意:这仅适用于zip存档中的单个文件!

对于zip支持中的多个文件,请检查以下回答:

我有类似问题。我尝试了此操作,但出现了错误。您能提供帮助吗?val zipFileRDD=sc.binaryFiles(zipFile).flatMap{case(名称:String,内容:PortableDataStream)=>new ZipInputStream(content.open)}>>:95:错误:类型不匹配;>找到:java.util.zip.ZipInputStream>必需:TraversableOnce[?]>val-zipFileRDD=sc.binaryFiles(zipFile).flatMap{case(name,content)=>new ZipInputStream(content.open)}您没有关闭连接。有没有想过使用包含多个zip文件(分区)的目录的方法?这对readFile非常有效,数据源api(如CSV reader,CSV=>dataframe)如何?zipfile_对象是什么,如何调用它并显示内容?请提供示例。我有一个CSV.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)
            // this solution works only for single file in the zip
            val entry = zis.getNextEntry
            val br = new BufferedReader(new InputStreamReader(zis))
            Stream.continually(br.readLine()).takeWhile(_ != null)
          }
      } else {
        sc.textFile(path, minPartitions)
      }
    }
  }
import com.github.atais.spark.Implicits.ZipSparkContext
sc.readFile(path)