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