2011-04-12 90 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); 
      }