8

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

4

3 回答 3

20

您正在寻找的方法称为 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))
于 2011-04-12T12:28:49.483 回答
0

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

方法 #1:根据您的数据大小,使用以下 HDFS 命令(在此处找到,第 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 的类,其中包含配置、文件系统实例以及其他辅助方法)

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-")

于 2013-06-17T12:43:15.590 回答
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);
            }
于 2016-01-14T12:17:14.587 回答