2011-04-12 78 views
8

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

回答

19

您正在查找的方法称为listStatus(路径)。 它只是将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)) 
+0

非常感谢您的帮助。 – nabeelmukhtar 2011-04-12 12:31:50

+1

@Thomas, listStatus也似乎返回其他文件,例如, _SUCCESS – 2011-11-27 23:57:16

+0

是的,但这不是我的问题;)你必须自己筛选 – 2011-11-28 06:17:21

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

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); 
      }