如何使用wholeTextFiles读取Spark中的gz文件

时间:2014-06-25 07:32:55

标签: hadoop gzip apache-spark gz

我有一个包含许多小.gz文件的文件夹(压缩的csv文本文件)。我需要在我的Spark工作中阅读它们,但问题是我需要根据文件名中的信息进行一些处理。因此,我没有使用:

JavaRDD<<String>String> input = sc.textFile(...)

因为据我所知,我无法以这种方式访问​​文件名。相反,我用过:

JavaPairRDD<<String>String,String> files_and_content = sc.wholeTextFiles(...);

因为这样我获得了一对文件名和内容。 但是,似乎这样,输入阅读器无法从gz文件中读取文本,而是读取二进制Gibberish。

所以,我想知道我是否可以设置它以某种方式阅读文本,或者使用sc.textFile(...)

访问文件名

2 个答案:

答案 0 :(得分:2)

您无法使用wholeTextFiles读取gzip压缩文件,因为它使用了无法读取gzip压缩文件的CombineFileInputFormat,因为they are not splittable(来源证明):

  override def createRecordReader(
      split: InputSplit,
      context: TaskAttemptContext): RecordReader[String, String] = {

    new CombineFileRecordReader[String, String](
      split.asInstanceOf[CombineFileSplit],
      context,
      classOf[WholeTextFileRecordReader])
  }

您可以将newAPIHadoopFilewholefileinputformat一起使用(不是内置于hadoop中,但在整个互联网上)以使其正常工作。

UPDATE 1:我不认为WholeFileInputFormat会工作,因为它只是获取文件的字节,这意味着您可能必须编写自己的类,可能会扩展WholeFileInputFormat以确保它解压缩字节

另一种选择是使用GZipInputStream

自行解压缩字节

更新2:如果你有权访问目录名,就像下面OP的评论一样,你可以得到这样的所有文件。

Path path = new Path("");
FileSystem fileSystem = path.getFileSystem(new Configuration()); //just uses the default one
FileStatus []  fileStatuses = fileSystem.listStatus(path);
ArrayList<Path> paths = new ArrayList<>();
for (FileStatus fileStatus : fileStatuses) paths.add(fileStatus.getPath());

答案 1 :(得分:0)

使用spark连接S3时遇到了同样的问题。

我的文件是一个没有扩展名的gzip csv。

JavaPairRDD<String, String> fileNameContentsRDD = javaSparkContext.wholeTextFiles(logFile);

此方法返回了已损坏的值

我使用下面的代码解决了它:

JavaPairRDD<String, String> fileNameContentsRDD = javaSparkContext.wholeTextFiles(logFile+".gz");

通过将.gz添加到S3 URL,spark会自动选择文件并像gz文件一样读取它。(看似错误的方法但解决了我的问题。