問題1:編寫文件輸出到不同的目錄 - 你可以用下面的方法做:
1.使用MultipleOutputs類:
它的偉大您可以使用MultipleOutput創建多個命名輸出文件。如您所知,我們需要在您的驅動程序代碼中添加此項。
MultipleOutputs.addNamedOutput(job, "OutputFileName", OutputFormatClass, keyClass, valueClass);
API提供兩個重載寫入方法來實現這一點。
multipleOutputs.write("OutputFileName", new Text(Key), new Text(Value));
現在,寫輸出文件分離輸出目錄,你需要使用一個重載write方法與基本輸出路徑的額外參數。
multipleOutputs.write("OutputFileName", new Text(key), new Text(value), baseOutputPath);
請記住在您的每個實施中更改您的baseOutputPath。
2.重命名/移動在驅動程序類文件:
這可能是寫輸出到多個目錄中的最簡單的黑客攻擊。使用multipleOutputs並將所有輸出文件寫入單個輸出目錄。但是每個類別的文件名稱需要不同。
假設您想要創建3組不同的輸出文件的,第一步是在驅動程序中註冊一個名爲輸出文件:
MultipleOutputs.addNamedOutput(job, "set1", OutputFormatClass, keyClass, valueClass);
MultipleOutputs.addNamedOutput(job, "set2", OutputFormatClass, keyClass, valueClass);
MultipleOutputs.addNamedOutput(job, "set3", OutputFormatClass, keyClass, valueClass);
此外,創建不同的輸出目錄或你想要的目錄結構在驅動程序代碼,與實際輸出目錄一起:
Path set1Path = new Path("/hdfsRoot/outputs/set1");
Path set2Path = new Path("/hdfsRoot/outputs/set2");
Path set3Path = new Path("/hdfsRoot/outputs/set3");
最後重要的一步就是重新命名根據他們的名字輸出文件。如果工作成功,
FileSystem fileSystem = FileSystem.get(new Configuration);
if (jobStatus == 0) {
// Get the output files from the actual output path
FileStatus outputfs[] = fileSystem.listStatus(outputPath);
// Iterate over all the files in the output path
for (int fileCounter = 0; fileCounter < outputfs.length; fileCounter++) {
// Based on each fileName rename the path.
if (outputfs[fileCounter].getPath().getName().contains("set1")) {
fileSystem.rename(outputfs[fileCounter].getPath(), new Path(set1Path+"/"+anyNewFileName));
} else if (outputfs[fileCounter].getPath().getName().contains("set2")) {
fileSystem.rename(outputfs[fileCounter].getPath(), new Path(set2Path+"/"+anyNewFileName));
} else if (outputfs[fileCounter].getPath().getName().contains("set3")) {
fileSystem.rename(outputfs[fileCounter].getPath(), new Path(set3Path+"/"+anyNewFileName));
}
}
}
注意:這不會增加任何重要的開銷,因爲我們只是從一個目錄移動到另一個目錄。選擇任何特定的方法取決於您的實施的性質。總之,這種方法基本上將所有使用不同名稱的輸出文件寫入同一個輸出目錄,並且當作業成功完成時,我們重命名基本輸出路徑並將文件移動到不同的輸出目錄。
問題2:從輸入文件夾(S)讀取特定文件:
你絕對可以使用MultipleInputs類目錄中讀取特定的輸入文件。
根據您的輸入路徑/文件名稱,您可以將輸入文件傳遞給相應的Mapper實現。
案例1:如果所有的輸入文件是在一個單獨的目錄:
FileStatus inputfs[] = fileSystem.listStatus(inputPath);
for (int fileCounter = 0; fileCounter < inputfs.length; fileCounter++) {
if (inputfs[fileCounter].getPath().getName().contains("set1")) {
MultipleInputs.addInputPath(job, inputfs[fileCounter].getPath(), TextInputFormat.class, Set1Mapper.class);
} else if (inputfs[fileCounter].getPath().getName().contains("set2")) {
MultipleInputs.addInputPath(job, inputfs[fileCounter].getPath(), TextInputFormat.class, Set2Mapper.class);
} else if (inputfs[fileCounter].getPath().getName().contains("set3")) {
MultipleInputs.addInputPath(job, inputfs[fileCounter].getPath(), TextInputFormat.class, Set3Mapper.class);
}
}
案例2:如果所有的輸入文件不在一個目錄:
我們可以即使輸入文件位於不同目錄中,也基本上使用上述相同的方法。遍歷基本輸入路徑並檢查文件路徑名稱以獲得匹配條件。或者,如果文件位於完全不同的位置,最簡單的方法是單獨添加到多個輸入。
MultipleInputs.addInputPath(job, Set1_Path, TextInputFormat.class, Set1Mapper.class);
MultipleInputs.addInputPath(job, Set2_Path, TextInputFormat.class, Set2Mapper.class);
MultipleInputs.addInputPath(job, Set3_Path, TextInputFormat.class, Set3Mapper.class);
希望這有助於!謝謝。
您能詳細解答一下答案嗎?你如何複製MultipleOutputs代碼? – 2012-07-14 12:33:08
感謝您的回覆 – 2012-07-14 15:36:58
它的工作!我可以輸出到不同的文件夾... – 2012-07-14 16:03:44