Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在MapReduce中使用globStatus筛选输入文件_Java_Hadoop_Mapreduce_Cloudera - Fatal编程技术网

Java 在MapReduce中使用globStatus筛选输入文件

Java 在MapReduce中使用globStatus筛选输入文件,java,hadoop,mapreduce,cloudera,Java,Hadoop,Mapreduce,Cloudera,我有很多输入文件,我想根据最后附加的日期处理选定的文件。我现在不知道在哪里使用globStatus方法来过滤文件 我有一个定制的RecordReader类,我试图在它的下一个方法中使用globStatus,但没有成功 public boolean next(Text key, Text value) throws IOException { Path filePath = fileSplit.getPath(); if (!processed) { key.se

我有很多输入文件,我想根据最后附加的日期处理选定的文件。我现在不知道在哪里使用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方法包含两个辅助参数,允许您过滤文件。第一个是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
就是这样一个界面:

public interface PathFilter {
    boolean accept(Path path);
}
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) {}
        }
    }
}
因此,您可以实现该接口并实现
accept
方法,在该方法中,您可以将逻辑放入筛选文件中

此示例允许您定义一个
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
实现过滤输入

EDIT:由于必须在
setInputPathFilter
中传递类,因此不能直接传递参数,但应该能够通过使用
配置来执行类似操作。如果将
regexcludepath过滤器
也从
Configured
扩展,则可以返回一个
Configuration
对象,该对象之前已使用所需的值进行了初始化,因此可以在过滤器内获取这些值,并在
accept
中对其进行处理

例如,如果按如下方式初始化:

public interface PathFilter {
    boolean accept(Path path);
}
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) {}
        }
    }
}
然后,您可以这样定义过滤器:

public interface PathFilter {
    boolean accept(Path path);
}
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:原始代码存在一些问题,请查看更新的类。您还需要删除构造函数,因为它不再被使用,并检查它是否是一个目录,在这种情况下,您应该返回true,以便目录的内容也可以被过滤。

对于阅读本文的任何人,我可以说“请不要在过滤器中做任何比验证路径更复杂的事情”。具体地说:不要检查文件是否为目录,获取其大小等。等待list/glob操作返回,然后使用填充的
FileStatus
条目中的信息在那里进行筛选

为什么??直接或通过
isDirectory()
getFileStatus()
的所有调用都是对文件系统的不必要调用,这些调用会在HDFS集群上增加不必要的namenode负载。更重要的是,针对S3和其他对象存储,每个操作都可能发出多个HTTPS请求,而这些请求确实需要可测量的时间。更好的是,如果S3认为您在整个计算机集群中发出的请求过多,它将限制您。你不会想要的

直到调用后,您返回的文件状态条目是来自对象存储的列表命令的条目,通常每个HTTPS请求返回数千个文件条目,因此效率更高


要了解更多详细信息,请查看org.apache.hadoop.fs.s3a.S3AFileSystem的源代码。我阅读了这些页面,我的问题是我在代码中的什么地方使用它?我可以在记录阅读器中使用它吗?@Expressions\u你可以调用
FileInputFormat.setInputPathFilter(JobConf,PathFilter)
,这样你就可以过滤你的输入了,你真的不需要一个记录阅读器就可以了。我有一个记录阅读器用于不同的用途。但是,当我创建一个实现PathFilter接口的类时,我在使用FileInputFormat.setInputPathFilter(JobConf,PathFilter)方法时收到了以下消息。方法setInputPathFilter(JobConf,ClassTry with
FileInputFormat.setInputPathFilter(JobConf,RegexIncludePathFilter.class);
。但是我如何将regex传递给它以查找呢?