java - 在 MapReduce 中使用 globStatus 过滤输入文件

标签 java hadoop mapreduce cloudera

我有很多输入文件,我想根据最后附加的日期处理选定的文件。我现在对在哪里使用 globStatus 方法过滤文件感到困惑。

我有一个自定义的 RecordReader 类,我试图在它的下一个方法中使用 globStatus,但没有成功。

public boolean next(Text key, Text value) throws IOException {
    Path filePath = fileSplit.getPath();

    if (!processed) {
        key.set(filePath.getName());

        byte[] contents = new byte[(int) fileSplit.getLength()];
        value.clear();
        FileSystem fs = filePath.getFileSystem(conf);
        fs.globStatus(new Path("/*" + date));
        FSDataInputStream in = null;

        try {
            in = fs.open(filePath);
            IOUtils.readFully(in, contents, 0, contents.length);
            value.set(contents, 0, contents.length);
        } finally {
            IOUtils.closeStream(in);
        }
        processed = true;
        return true;
    }
    return false;
}

我知道它返回一个 FileStatus 数组,但我如何使用它来过滤文件。有人可以解释一下吗?

最佳答案

globStatus 方法采用 2 个免费参数,允许您过滤文件。第一个是 glob 模式,但有时 glob 模式不足以过滤特定文件,在这种情况下,您可以定义一个 PathFilter

关于 glob 模式,支持以下内容:

Glob   | Matches
-------------------------------------------------------------------------------------------------------------------
*      | Matches zero or more characters
?      | Matches a single character
[ab]   | Matches a single character in the set {a, b}
[^ab]  | Matches a single character not in the set {a, b}
[a-b]  | Matches a single character in the range [a, b] where a is lexicographically less than or equal to b
[^a-b] | Matches a single character not in the range [a, b] where a is lexicographically less than or equal to b
{a,b}  | Matches either expression a or b
\c     | Matches character c when it is a metacharacter

PathFilter 只是一个像这样的接口(interface):

public interface PathFilter {
    boolean accept(Path path);
}

因此您可以实现此接口(interface)并实现 accept 方法,您可以将您的逻辑放入过滤文件。

取自 Tom White's excellent book 的示例它允许您定义一个 PathFilter 来过滤与特定正则表达式匹配的文件:

public class RegexExcludePathFilter implements PathFilter {
    private final String regex;

    public RegexExcludePathFilter(String regex) {
        this.regex = regex;
    }

    public boolean accept(Path path) {
        return !path.toString().matches(regex);
    }
}

您可以在初始化作业时通过调用 FileInputFormat.setInputPathFilter(JobConf, RegexExcludePathFilter.class) 来使用 PathFilter 实现直接过滤您的输入。

编辑:由于您必须在 setInputPathFilter 中传递类,因此您不能直接传递参数,但您应该能够通过使用配置。如果您使 RegexExcludePathFilter 也从 Configured 扩展,您可以取回一个 Configuration 对象,您之前已使用所需的值对其进行了初始化,因此您可以在过滤器中取回这些值并在 accept 中处理它们。

例如,如果你这样初始化:

conf.set("date", "2013-01-15");

然后你可以这样定义你的过滤器:

public class RegexIncludePathFilter extends Configured implements PathFilter {
    private String date;
    private FileSystem fs;

    public boolean accept(Path path) {
        try {
            if (fs.isDirectory(path)) {
                return true;
            }
        } catch (IOException e) {}
        return path.toString().endsWith(date);
    }

    public void setConf(Configuration conf) {
        if (null != conf) {
            this.date = conf.get("date");
            try {
                this.fs = FileSystem.get(conf);
            } catch (IOException e) {}
        }
    }
}

编辑 2:原始代码存在一些问题,请查看更新后的类(class)。您还需要删除构造函数,因为它不再被使用,并检查它是否是一个目录,在这种情况下您应该返回 true 以便目录的内容也可以被过滤。

关于java - 在 MapReduce 中使用 globStatus 过滤输入文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14332330/

相关文章:

java - Liquibase 在执行变更集之前检查表名称长度

java - 如何使用java中的键获取Json值?

hadoop - 为什么这个简单的 Hive 表声明有效?仿佛变魔术

java - 执行 BufferedReader.close() 时 Hadoop FileSystem 关闭异常

链接对象上的 javaScript map/reduce

java - 如何更改 Play Framework 2 "test"设置以显示完整的堆栈跟踪?

java - 图形未出现在窗口中

hadoop - 使用elephant-bird配合hive读取protobuf数据

hadoop - 检查并验证Hadoop mapreduce中的节点数?

hadoop - 利用Hadoop的MapReduce中的关系名/表名/文件名