我有一个S3存储桶,其中填充了没有文件扩展名的Gz文件。例如s3://mybucket/1234502827-34231
sc.textFile
使用该文件扩展名来选择解码器。我发现很多关于处理自定义文件扩展名的博客文章,但没有关于丢失文件扩展名
我认为解决方案可能是sc.binaryFiles
并手动解压缩文件。
另一种可能性是弄清楚sc.textFile如何找到文件格式。我不清楚这些classOf[]
调用的工作原理。
def textFile(
path: String,
minPartitions: Int = defaultMinPartitions): RDD[String] = withScope {
assertNotStopped()
hadoopFile(path, classOf[TextInputFormat], classOf[LongWritable], classOf[Text],
minPartitions).map(pair => pair._2.toString).setName(path)
}
答案 0 :(得分:2)
您是否可以尝试将以下ZIP文件解决方案与gzipFileInputFormat库结合使用?
此处 - How to open/stream .zip files through Spark? 你可以看看如何使用ZIP:
mainModule.directive("telephoneValidation", function ($compile) {
return {
restrict: "A",
replace: true,
link:
function (scope, element, attrs) {
element.attr('data-ng-pattern','^[\( ]{0,1}[\+ ]{0,1}[0-9 ]+[\)]{0,1}[0-9\- ]*$/');
$compile(element.contents())(scope);
element.removeAttr('telephone-validation').empty();
}
};
});
gzipFileInputFormat:
有关newAPIHadoopFile()的一些详细信息,请访问: http://spark.apache.org/docs/latest/api/python/pyspark.html
答案 1 :(得分:1)
我找到了几个几乎符合我需求的例子。这是我用来解析用GZ压缩的文件的最终代码。
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream
import org.apache.spark.input.PortableDataStream
import scala.util.Try
import java.nio.charset._
def extractBSM(ps: PortableDataStream, n: Int = 1024) = Try {
val gz = new GzipCompressorInputStream(ps.open)
Stream.continually {
// Read n bytes
val buffer = Array.fill[Byte](n)(-1)
val i = gz.read(buffer, 0, n)
(i, buffer.take(i))
}
// Take as long as we've read something
.takeWhile(_._1 > 0)
.map(_._2)
.flatten
.toArray
}
def decode(charset: Charset = StandardCharsets.UTF_8)(bytes: Array[Byte]) = new String(bytes, StandardCharsets.UTF_8)
val inputFile = "s3://my-bucket/157c96bd-fb21-4cc7-b340-0bd4b8e2b614"
val rdd = sc.binaryFiles(inputFile).flatMapValues(x => extractBSM(x).toOption).map( x => decode()(x._2) )
val rdd2 = rdd.flatMap { x => x.split("\n") }
rdd2.take(10).foreach(println)
答案 2 :(得分:0)
您可以创建自己的自定义编解码器来解码文件。您可以首先扩展GzipCodec并覆盖getDefaultExtension方法,在此方法中,您将空字符串作为扩展名返回。
编辑:由于实施CompressionCodecFactory的方式,该解决方案在所有情况下均不起作用。例如:默认情况下,.lz4的编解码器已加载。这意味着,如果要加载的文件名以4结尾,则将选择该编解码器而不是自定义编解码器(不带扩展名)。由于该编解码器与扩展名不匹配,因此以后会被抛弃,不再使用编解码器。
Java:
package com.customcodec;
import org.apache.hadoop.io.compress.GzipCodec;
public class GzipCodecNoExtension extends GzipCodec {
@Override
public String getDefaultExtension() {
return "";
}
}
在spark应用中,您只需注册编解码器:
SparkConf conf = new SparkConf()
.set("spark.hadoop.io.compression.codecs", "com.customcodec.GzipCodecNoExtension");
答案 3 :(得分:0)
您可以使用地图功能读取二进制文件并进行解压缩。
JavaRDD<Tuple2<String, PortableDataStream>> rawData = spark.sparkContext().binaryFiles(readLocation, 1).toJavaRDD();
JavaRDD<String> decompressedData = rawData.map((Function<Tuple2<String, PortableDataStream>, String>) stringPortableDataStreamTuple2 -> {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream s = new GZIPInputStream(new ByteArrayInputStream(stringPortableDataStreamTuple2._2.toArray()));
IOUtils.copy(s, out);
return new String(out.toByteArray());
});
对于JSON内容,您可以使用
将其读入数据集Dataset co = spark.read().json(decompressedData);