Compression apachespark中的Zip支持
我读过Spark对gzip类输入文件的支持,我想知道对不同类型的压缩文件(如.zip文件)是否也有相同的支持。到目前为止,我已经尝试过计算压缩在zip文件下的文件,但Spark似乎无法成功读取其内容 我已经看了Hadoop的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
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)