2015-12-31 52 views
3

我需要處理文本文件的文件夾。文本文件可以是任何擴展名。識別文件夾中用於處理文件的擴展名使用hadoop mapreduce

對於每個擴展,我們需要單獨的自定義閱讀器來處理hadoop中的文件。

folder1/ 
    Data1.pdf 
    Data2.xml 
    Data3.html 
    Data4.txt 
    Data5.csv 

什麼是更好的方式來獲得文件夾中文件的擴展名併爲我的MR Job設置Custom InputFormat?

我做了什麼至今

驅動

FileStatus[] stati = null; 
try { 
    stati = fs.listStatus(in); 
} catch (FileNotFoundException e) { 
    e.printStackTrace(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 
for (FileStatus status : stati) { 
    Path path = status.getPath(); 
    System.out.println("Path----> "+path); 
    /* 
    * get file extension 
    */ 
    String ext = FilenameUtils.getExtension(path.toString()); 
    System.out.println("ext--->"+ext); 
    if(ext.equals("pdf")){ 
      //custom pdf record reader 
     job.setInputFormatClass(PdfInputFormat.class); 
    } 
    else{ 
     job.setInputFormatClass(TextInputFormat.class); 
    } 
} 

但這不會witin的folder1工作,但如果文件夾1只包含.pdf文件能正常工作。

我錯過了什麼嗎?

希望,因爲我在文件夾迭代這是行不通的罰款(比如文件夾2 - > Data5.pdf,Data4.csv)。這setInputFormatClass不會向 TextInputFormat.addInputPath任何影響(作業中,)作爲inputformat將使用Data4.csv的最後迭代值進行設置。

job.setMapOutputKeyClass(Text.class); 
    job.setMapOutputValueClass(Text.class); 
    job.setOutputKeyClass(NullWritable.class); 
    job.setOutputValueClass(NullWritable.class); 
    job.setMapperClass(MyMapper.class); 
    job.setReducerClass(MyReducer.class); 
    job.setOutputFormatClass(TextOutputFormat.class); 
    try { 
     TextInputFormat.addInputPath(job, in); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    TextOutputFormat.setOutputPath(job, out); 

編輯

Job job = null; 
try { 
job = new Job(conf, "TextMining"); 
} catch (IOException e) { 
e.printStackTrace(); 
} 
/* 
* check entension 
*/ 
for (FileStatus status : stati) { 
Path path = status.getPath(); 
System.out.println("Path----> "+path); 
/* 
    * get file extension 
    */ 
String ext = FilenameUtils.getExtension(path.toString()); 
System.out.println("ext--->"+ext); 
if(ext.equals("pdf")){ 
     System.out.println("Pdf File Format"); 
     // MultipleInputs.addInputPath(job, path,PdfInputFormat.class, PDFStemmingMapper.class); 
     job.setInputFormatClass(PdfInputFormat.class); 
} 
else if(ext.equals("xlsx")){ 
     System.out.println("Excel File Format"); 
     job.setInputFormatClass(ExcelInputFormat.class); 
} 
else{ 
     System.out.println("normal Text File"); 
     job.setInputFormatClass(TextInputFormat.class); 
} 
} 
job.setJarByClass(Driver.class); 
job.setMapOutputKeyClass(Text.class); 
job.setMapOutputValueClass(Text.class); 
job.setOutputKeyClass(NullWritable.class); 
job.setOutputValueClass(NullWritable.class); 
//job.setInputFormatClass(TextInputFormat.class); 
job.setMapperClass(MyMapper.class); 
job.setReducerClass(MyReducer.class); 
job.setOutputFormatClass(TextOutputFormat.class); 


// try { 
    // TextInputFormat.addInputPath(job, in); 
    // } catch (IOException e) { 
    // e.printStackTrace(); 
    // } 
    TextOutputFormat.setOutputPath(job, out); 

我想實現有點像上面。 但是這沒有給出任何輸出。 請建議。

回答

0

對於映射器,預期的輸入是一條記錄(由值表示)。 InputFormat是如何構造這個記錄並傳遞給map方法的。

例:默認輸入格式的TextInputFormat,將考慮一條線在一個文件中作爲記錄。這通常適用於txt/xsv文件。

對於其他類型的文件,更好的辦法是使用自定義的InputFormat,它知道如何代表一個記錄。 (在XML中,記錄可以是一個子塊)

如果你已經有InputFormat類你已經確定的所有文件類型,那麼你可以使用MultipleInputs。

看看這裏的Javadoc https://hadoop.apache.org/docs/r2.7.0/api/org/apache/hadoop/mapreduce/lib/input/MultipleInputs.html

識別擴展名可以用FileSystem API可

+0

我如何才能將與MultipleInputs?這足以滿足我的情況。 MultipleInputs有助於加入不同的文件,如[this](http://unmeshasreeveni.blogspot.in/2014/12/joining-two-files-using-multipleinput.html)。MultipleInputs是否做得比這更多 –

+0

MultipleInputs通常用於處理不同類型的文件,生成一個通用的輸出,因爲它是OR,所以可以進一步加入其他處理。例如:1)。從不同類型的文件(XML,JSON,TXT等)中提取訂單詳細信息。 2)加入是另一種類型的用例,其中「訂單和商品詳細信息」位於不同的文件中,並且您希望一條輸出記錄結合兩者的詳細信息。 **您的用例是什麼?** –

+0

第一個是我的用例。我需要處理具有不同文件擴展名的文件夾中的文件 –

1

從上下文中來完成,獲得輸入分流,然後從路徑獲取路徑&名。

Context => getInputSplit() => getPath => getName()

一旦你的名字,找到該索引lastIndexOf(".")和子。

現在,您在子字符串中有擴展名並將其用於比較。

編輯:

是下面的方法對你是否可行?

  1. 對於每種類型的擴展都有單獨的映射器。

  2. 在Driver類中添加以下行。

    MultipleInputs.addInputPath(job, path_pdf,inputFormatClass, PDFMapper.class) 
    
    MultipleInputs.addInputPath(job, path_xml, inputFormatClass,XMLMapper.class) 
    
    MultipleInputs.addInputPath(job, path_html,inputFormatClass,HTMLMapper.class) 
    
    MultipleInputs.addInputPath(job, path_csv,inputFormatClass,CVSMapper.class) 
    
+0

我應該得到輸入拆分 - > getPath-> getName並檢查擴展名或獲取Driver中的filestatus並遍歷filestatus並獲取路徑?哪種方法更好?因爲我們需要從驅動類中設置「setInputFormatClass」權限? –

+0

第一個更好。 –

+0

好。但仍然有人懷疑。「Context => getInputSplit()=> getPath => getName()」在mapper類中是不是應該使用?但是,如何爲我的不同文件格式在Driver類中設置自定義輸入格式? –

相關問題