如何在运行Hadoop MapReduce作业时将文件名/文件内容作为MAP的键/值输入?

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

当我启动MapReduce作业时,我希望map函数将Filename作为键,将Binary Contents作为值。 然后我想创建一个流阅读器,我可以将其传递给PDF解析器库。 如何实现Map Phase的键/值对是filename / filecontents?

我正在使用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); } 

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

提前致谢!

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

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

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

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

您可以使用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(); }