2012-07-31 148 views
3

我有大約1000 files,每個文件的大小爲1GB。我需要在所有這些1000 files中找到一個字符串,以及哪些文件包含該特定的字符串。我正在使用Hadoop文件系統,所有這些1000 files都在Hadoop文件系統中。使用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作業做這種問題的原因...

+0

是你需要找到包含在文件中的文本的一部分字符串或者是它的文件名? – rtheunissen 2012-07-31 05:45:08

+0

我認爲OP意味着在文件內容中搜索。否則他不會提到文件大小。 – 2012-07-31 05:46:43

+0

我需要在所有這1000個文件內容中找到字符串。哪些文件包含特定的字符串是我的目標。 – ferhan 2012-07-31 05:54:57

回答

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的數據流作業:

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

感謝喬希的建議。你提供的解決方案,我無法理解,你可以請更清楚,以便我可以理解,也不知道在這種情況下應該是什麼樣的Mapper,因爲我是MapReduce作業的新手,所以這是原因我遇到了很多問題。任何有關我的問題場景的工作示例基礎都將幫助我理解MapReduce的工作原理。 – ferhan 2012-07-31 06:29:11

+0

@rjchar:我正在使用Hadoop Streaming API,它允許我使用shell腳本或其他實用程序編寫mappers和reducers。在我的回答中,Python程序充當映射器。如果您是MapReduce的新手,Google Code University有一個很好的[概述](https://code.google.com/edu/parallel/mapreduce-tutorial.html)MapReduce模型,而[Hadoop MapReduce教程] (http://hadoop.apache.org/mapreduce/docs/current/mapred_tutorial.html)解釋瞭如何在Hadoop中編寫MapReduce程序。 – 2012-07-31 06:37:46

+0

那麼你寫的Python程序,那是一個Mapper?我可以運行你直接在hadoop集羣上給我的例子..對吧?而且'-input'在這裏意味着什麼,它意味着所有1000個文件在那裏的文件夾? – ferhan 2012-07-31 06:40:52

0

你可以嘗試這樣的事情,雖然我不知道這是否是一種有效的方式去了解它。讓我知道它是否有效 - 我沒有測試它或任何東西。

你可以使用它是這樣的:的Java SearchFiles /技術/ DPS /實際你好確保你當然從相應的目錄中運行它。

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; 
    } 
} 
+0

這個Java程序需要兩個參數?我猜..第一個參數是包含所有這1000個文件和第二個參數的文件夾,它需要的是您要搜索的字符串?而且我還更新了我的問題。你能讓我知道這將比Unix grep更快嗎?而且我正在使用Hadoop集羣,所以我可以運行這個Java程序嗎?或者我需要編寫一些自定義映射器和Reducer來解決這個問題? – ferhan 2012-07-31 06:09:40

+0

堅持......我正在更新一下。 – rtheunissen 2012-07-31 06:10:37

+0

這個答案不適用於Hadoop。它假定本地文件,而不是HDFS文件。再加上它會需要永遠。 – 2012-07-31 06:10:56

1

要獲得當前正在處理的文件名,這樣做:

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

當你被記錄搜索你的文件記錄,當你看到hello,發出上述路徑(也許行或還要別的嗎)。

將reducer的數量設置爲0,他們在這裏沒有做任何事情。


'行格式分隔'是否意味着行被換行符分隔?在這種情況下,TextInputFormatLineRecordReader可以在此處正常工作。

+0

感謝orangeoctopus的建議。我是MapReduce世界的新手,所以對此沒有太多線索。如果你能給我簡單的示例基礎來解決我的問題場景,那麼我可以嘗試用Reducer設置爲零的自定義映射器來測試它,然後我將能夠更好地理解。這對我很有幫助。 – ferhan 2012-07-31 06:14:02

+0

你能否給我提供一些樣本示例,以便我能更好地理解我的情況。這對我瞭解自定義Mapper和Reduce的事情會有很大的幫助。 – ferhan 2012-07-31 06:42:24

相關問題