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