【问题标题】:How to get Filename/File Contents as key/value input for MAP when running a Hadoop MapReduce Job?运行 Hadoop MapReduce 作业时,如何获取文件名/文件内容作为 MAP 的键/值输入?
【发布时间】:2011-04-19 12:13:04
【问题描述】:

我正在创建一个程序来分析 PDF、DOC 和 DOCX 文件。这些文件存储在 HDFS 中。

当我开始我的 MapReduce 工作时,我希望 map 函数将文件名作为键,将二进制内容作为值。然后我想创建一个流阅读器,我可以将它传递给 PDF 解析器库。如何实现 Map Phase 的键/值对是文件名/文件内容?

我正在使用 Hadoop 0.20.2

这是开始工作的旧代码:

public static void main(String[] args) throws Exception {
 JobConf conf = new JobConf(PdfReader.class);
 conf.setJobName("pdfreader");

 conf.setOutputKeyClass(Text.class);
 conf.setOutputValueClass(IntWritable.class);

 conf.setMapperClass(Map.class);
 conf.setReducerClass(Reduce.class);

 conf.setInputFormat(TextInputFormat.class);
 conf.setOutputFormat(TextOutputFormat.class);

 FileInputFormat.setInputPaths(conf, new Path(args[0]));
 FileOutputFormat.setOutputPath(conf, new Path(args[1]));

 JobClient.runJob(conf);
}

我知道还有其他输入格式类型。但是有没有一个可以完全满足我的要求?我发现文档很模糊。如果有可用的,那么 Map 函数输入类型应该如何?

提前致谢!

【问题讨论】:

  • 对于新读者:看看 Hadoop Archives (HAR) 和 Sequence 文件,它们更适合输入到 Hadoop。

标签: java hadoop mapreduce distributed-system


【解决方案1】:

解决方案是创建您自己的 FileInputFormat 类来执行此操作。 您可以从此 FileInputFormat 接收的 FileSplit (getPath) 访问输入文件的名称。 请务必否决 FileInputformat 的 isSplitable 以始终返回 false。

您还需要一个自定义的 RecordReader,它将整个文件作为单个“记录”值返回。

在处理太大的文件时要小心。您将有效地将整个文件加载到 RAM 中,并且任务跟踪器的默认设置是只有 200MB RAM 可用。

【讨论】:

  • 大文件如何处理?
  • 简单:分配足够的内存。如果您的文件大于最大可能的 RAM,那么这个愿望根本不可能。
【解决方案2】:

作为您方法的替代方案,可以将二进制文件直接添加到 hdfs。然后,创建一个包含所有二进制文件的 dfs 路径的输入文件。这可以使用Hadoop's FileSystem 类动态完成。最后,再次使用 FileSystem 创建一个通过打开输入流来处理输入的映射器。

【讨论】:

  • 嗨,布伦特,感谢您的回答。如果我找不到更好的选择,我会使用它!我可能会失去 Hadoop 附带的 机架感知 功能。打开一个 dfs 文件名可能意味着打开一个位于“很远”的文件,而另一个文件可能是关闭的。 (我需要在一定程度上证明可扩展性和加速因素)
【解决方案3】:

你可以使用 WholeFileInputFormat (https://code.google.com/p/hadoop-course/source/browse/HadoopSamples/src/main/java/mr/wholeFile/?r=3)

在你可以通过这个命令获取的文件的映射器名称中:

public void map(NullWritable key, BytesWritable value, Context context) throws 
IOException, InterruptedException 
{       

Path filePath= ((FileSplit)context.getInputSplit()).getPath();
String fileNameString = filePath.getName();

byte[] fileContent = value.getBytes();

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多