使用Hadoop查找包含特定字符串的文件

时间:2012-07-31 04:05:49

标签: java hadoop mapreduce hive

我有大约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工作来解决这个问题的原因......

3 个答案:

答案 0 :(得分:4)

听起来你正在寻找类似grep的程序,使用Hadoop Streaming很容易实现(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流式传输作业,而不使用reducer:

$ 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"

输出将分为几个部分;要获得匹配列表,您可以简单地捕获文件(假设它们不是太大):

$ 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
... 

答案 1 :(得分:1)

要获取您当前正在处理的文件名,请执行以下操作:

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

当您按记录搜索文件记录时,当您看到hello时,会发出上述路径(也许是该行或其他任何内容)。

将减速器的数量设置为0,它们在这里没有做任何事情。


'row format delimited'是否意味着换行符分隔行?在这种情况下,TextInputFormatLineRecordReader可以正常使用。

答案 2 :(得分: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;
    }
}