3

私は周りにいて1000 files、各ファイルのサイズは1GB. 1000 filesそして、これらすべての文字列と、その特定の文字列を含むファイルを見つける必要があります。私は Hadoop ファイル システムを使用していますが、それら1000 filesはすべて Hadoop ファイル システムにあります。

すべて1000 filesが実際のフォルダーの下にあるため、以下のようにすると、すべての1000 files. そして、実際のフォルダーの下に特定の文字列helloが含まれているファイルを見つける必要があります。

bash-3.00$ hadoop fs -ls /technology/dps/real

そして、これはhdfsの私のデータ構造です-

row format delimited 
fields terminated by '\29'
collection items terminated by ','
map keys terminated by ':'
stored as textfile

特定の文字列を含むファイルを見つけられるように、この特定の問題を解決するために MapReduce ジョブを作成するにはどうすればよいでしょうか? 簡単な例は、私にとって非常に役立ちます。

アップデート:-

Unixでgrepを使用すると、上記の問題のシナリオを解決できますが、非常に遅く、実際の出力を取得するのに多くの時間がかかります-

hadoop fs -ls /technology/dps/real | awk '{print $8}' | while read f; do hadoop fs -cat $f | grep cec7051a1380a47a4497a107fecb84c1 >/dev/null && echo $f; done

それが、この種の問題を解決するための MapReduce ジョブを探していた理由です...

4

3 に答える 3

4

Hadoop ストリーミングを使用して簡単に実装できる grep のようなプログラムを探しているようです(Hadoop Java API も機能します)。

まず、処理中の行に検索文字列が含まれている場合に、処理中のファイルの名前を出力するマッパーを作成します。私は Python を使用しましたが、どの言語でも機能します。

#!/usr/bin/env python
import os
import sys

SEARCH_STRING = os.environ["SEARCH_STRING"]

for line in sys.stdin:
    if SEARCH_STRING in line.split():
        print os.environ["map_input_file"]

SEARCH_STRINGこのコードは、環境変数から検索文字列を読み取ります。ここでは、入力行を分割し、検索文字列が分割のいずれかに一致するかどうかを確認します。これを変更して、部分文字列検索を実行したり、正規表現を使用して一致を確認したりできます。

次に、このマッパーを使用し、リデューサーを使用せずに Hadoop ストリーミング ジョブを実行します。

$ bin/hadoop jar contrib/streaming/hadoop-streaming-*.jar \
    -D mapred.reduce.tasks=0
    -input hdfs:///data \
    -mapper search.py \
    -file search.py \
    -output /search_results \
    -cmdenv SEARCH_STRING="Apache"

出力はいくつかの部分に分けて書かれます。一致のリストを取得するには、ファイルを cat するだけです (ファイルが大きすぎない場合)。

$ bin/hadoop fs -cat /search_results/part-*
hdfs://localhost/data/CHANGES.txt
hdfs://localhost/data/CHANGES.txt
hdfs://localhost/data/ivy.xml   
hdfs://localhost/data/README.txt
... 
于 2012-07-31T06:24:36.977 に答える
1

現在処理中のファイル名を取得するには、次のようにします。

((FileSplit) context.getInputSplit()).getPath().getName() 

レコードごとにファイルを検索しているときに、 が表示されたらhello、上記のパス (および行など) を発行します。

レデューサーの数を 0 に設定します。ここでは何もしていません。


「行フォーマット区切り」とは、行が改行で区切られていることを意味しますか? その場合TextInputFormat、ここでは正常にLineRecordReader動作します。

于 2012-07-31T06:08:56.410 に答える
0

このようなことを試すことができますが、それが効率的な方法であるかどうかはわかりません. それが機能するかどうか教えてください-私はそれをテストしていません。

次のように使用できます: java SearchFiles /technology/dps/real helloもちろん、適切なディレクトリから実行するようにします。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

public class SearchFiles {

    public static void main(String[] args) throws IOException {
        if (args.length < 2) {
            System.err.println("Usage: [search-dir] [search-string]");
            return;
        }
        File searchDir = new File(args[0]);
        String searchString = args[1];
        ArrayList<File> matches = checkFiles(searchDir.listFiles(), searchString, new ArrayList<File>());
        System.out.println("These files contain '" + searchString + "':");
        for (File file : matches) {
            System.out.println(file.getPath());
        }
    }

    private static ArrayList<File> checkFiles(File[] files, String search, ArrayList<File> acc) throws IOException {
        for (File file : files) {
            if (file.isDirectory()) {
                checkFiles(file.listFiles(), search, acc);
            } else {
                if (fileContainsString(file, search)) {
                    acc.add(file);
                }
            }
        }
        return acc;
    }

    private static boolean fileContainsString(File file, String search) throws IOException {
        BufferedReader in = new BufferedReader(new FileReader(file));
        String line;
        while ((line = in.readLine()) != null) {
            if (line.contains(search)) {
                in.close();
                return true;
            }
        }
        in.close();
        return false;
    }
}
于 2012-07-31T06:03:04.403 に答える