以编程方式读取Hadoop Mapreduce程序的输出

时间:2011-04-12 11:01:01

标签: hadoop mapreduce hdfs

这可能是一个基本问题,但我无法在Google上找到答案 我有一个map-reduce作业,在其输出目录中创建多个输出文件。 我的Java应用程序在远程hadoop集群上执行此作业,在作业完成后,它需要使用org.apache.hadoop.fs.FileSystem API以编程方式读取输出。有可能吗?
应用程序知道输出目录,但不知道map-reduce作业生成的输出文件的名称。似乎没有办法以编程方式列出hadoop文件系统API中目录的内容。如何读取输出文件?
这似乎是一种常见的情况,我相信它有一个解决方案。但我错过了一些非常明显的事情。

3 个答案:

答案 0 :(得分:19)

您正在寻找的方法称为listStatus(Path)。 它只是将Path中的所有文件作为FileStatus数组返回。然后你可以简单地循环它们创建一个路径对象并阅读它。

    FileStatus[] fss = fs.listStatus(new Path("/"));
    for (FileStatus status : fss) {
        Path path = status.getPath();
        SequenceFile.Reader reader = new SequenceFile.Reader(fs, path, conf);
        IntWritable key = new IntWritable();
        IntWritable value = new IntWritable();
        while (reader.next(key, value)) {
            System.out.println(key.get() + " | " + value.get());
        }
        reader.close();
    }

对于Hadoop 2.x,您可以像这样设置阅读器:

 SequenceFile.Reader reader = 
           new SequenceFile.Reader(conf, SequenceFile.Reader.file(path))

答案 1 :(得分:0)

你有几个选择:这里有两个我有时会用的。

方法#1:根据您的数据大小,使用以下HDFS命令(找到here,第6项)

hadoop fs -getmerge hdfs-output-dir local-file
// example 
hadoop fs -getmerge /user/kenny/mrjob/ /tmp/mrjob_output
// another way
hadoop fs -cat /user/kenny/mrjob/part-r-* > /tmp/mrjob_output

“这将HDFS文件hdfs-output-dir / part- *连接到一个本地文件中。”

然后你可以只读一个文件。 (请注意,它位于本地存储而非HDFS中)

方法#2 :创建一个辅助方法:(我有一个名为HDFS的类,其中包含Configuration,FileSystem实例以及其他辅助方法)

public List<Path> matchFiles(String path, final String filter) {
        List<Path> matches = new LinkedList<Path>();
        try {
            FileStatus[] statuses = fileSystem.listStatus(new Path(path), new PathFilter() {
                       public boolean accept(Path path) {
                          return path.toString().contains(filter);
                       }
                    });  
            for(FileStatus status : statuses) {
                matches.add(status.getPath());
            }
        } catch(IOException e) {
        LOGGER.error(e.getMessage(), e);
        }
        return matches;
    }

然后您可以通过以下命令进行呼叫:hdfs.matchFiles("/user/kenny/mrjob/", "part-")

答案 2 :(得分:0)

            FSDataInputStream inputStream = fs.open(path);
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String record;
            while((record = reader.readLine()) != null) {
                int blankPos = record.indexOf(" ");
                System.out.println(record+"blankPos"+blankPos);
                String keyString = record.substring(0, blankPos);
                String valueString = record.substring(blankPos + 1);
                System.out.println(keyString + " | " + valueString);
            }