2

入力ファイルがたくさんあるので、最後に追加された日付に基づいて選択したファイルを処理したいと思います。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配列を返すことは知っていますが、ファイルをフィルタリングするためにどのように使用しますか。誰かが光を当ててくれませんか?

4

2 に答える 2

10

このglobStatusメソッドは、ファイルをフィルタリングできるようにする 2 つの補完的な引数を取ります。1 つ目は 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);
}

したがって、このインターフェイスを実装し、acceptロジックを配置してファイルをフィルター処理できるメソッドを実装できます。

特定の正規表現に一致するファイルをフィルタリングするように定義できるTom Whiteの優れた本からの例: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);
    }
}

ジョブを初期化するときにPathFilter呼び出すことにより、実装で入力を直接フィルタリングできます。FileInputFormat.setInputPathFilter(JobConf, RegexExcludePathFilter.class)

編集: でクラスを渡す必要がsetInputPathFilterあるため、引数を直接渡すことはできませんが、Configuration. 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 : 元のコードにはいくつかの問題がありました。更新されたクラスを参照してください。また、コンストラクターはもう使用されていないため削除する必要があります。また、それがディレクトリであるかどうかを確認する必要があります。その場合、ディレクトリの内容もフィルタリングできるように true を返す必要があります。

于 2013-01-15T06:55:03.723 に答える
3

これを読んでいる人には、「パスを検証するよりもフィルターで複雑なことをしないでください」と言えますか。具体的には、ファイルがディレクトリであること、サイズを取得することなどのチェックを行わないでください。リスト/グロブ操作が返されるまで待ってから、入力されたFileStatusエントリの情報を使用してそこでフィルタリングを行います。

なんで?へのこれらのすべての呼び出しはgetFileStatus()、直接または経由isDirectory()でファイルシステムに不要な呼び出しを行っており、HDFS クラスターに不要な namenode 負荷を追加する呼び出しを行っています。さらに重要なのは、S3 やその他のオブジェクト ストアに対して、各操作が複数の HTTPS リクエストを作成している可能性があり、実際にかなりの時間がかかることです。さらに良いことに、マシンのクラスター全体であまりにも多くのリクエストを行っていると S3 が判断した場合、S3 はユーザーを抑制します。あなたはそれを望んでいません。

Wit until after the call — 返されるファイル ステータス エントリは、オブジェクト ストアの list コマンドからのものであり、通常、HTTPS 要求ごとに数千のファイル エントリが返されるため、はるかに効率的です。

詳細については、のソースを調べてくださいorg.apache.hadoop.fs.s3a.S3AFileSystem

于 2016-08-24T15:51:15.913 に答える