我正在创建一个分析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函数输入类型应该如何显示?
提前致谢!
答案 0 :(得分:8)
解决方法是创建自己的FileInputFormat类来执行此操作。 您可以从此FileInputFormat接收的FileSplit访问输入文件的名称(getPath)。 请务必否决FileInputformat的isSplitable以始终返回false。
您还需要一个自定义RecordReader,它将整个文件作为单个“Record”值返回。
小心处理太大的文件。您将有效地将整个文件加载到RAM中,任务跟踪器的默认设置是只有200MB RAM可用。
答案 1 :(得分:1)
作为您的方法的替代方案,可以直接将二进制文件添加到hdfs。然后,创建一个包含所有二进制文件的dfs路径的输入文件。这可以使用Hadoop's FileSystem类动态完成。最后,创建一个映射器,通过打开输入流来处理输入,再次使用FileSystem。
答案 2 :(得分:1)
您可以使用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();
}