如何使用相同文件的分割提供馈送到映射器的文件的每一行?
基本上我想做的是
for each line in file-split
{
for each line in file{
//process
}
}
我可以使用java中的map reduce吗?
答案 0 :(得分:0)
实际上,当触发mapreduce作业时,它首先检查输入文件,为简单起见,我们只考虑一个大的输入文件!如果它的大小大于块大小,则作业跟踪器会按块大小拆分此文件,然后启动生成的No. of map tasks = No. of Splits
并将每个拆分传递给每个映射器任务以进行处理。因此,每个映射器将处理不超过一个拆分。
此外,如果输入文件大小小于块大小,则 jobtracker 会将其作为单独的拆分。
假设块大小为64MB,并且您有2个文件,每个文件大小为10MB,那么jobtracker将生成2个拆分!,因为根据FileInputFormat
,拆分可以只是一个文件(包含filesize< =块大小)或文件的一部分(如果其大小> blocksize)。
因此,一个mapper只会处理一个分割,也就是一个分割不能包含多个文件(对于FileInputFormat,默认格式为true,但是在组合文件输入格式的情况下它可以跨越多个文件)。
我猜你正在使用FilInputFormat。 HTH!
您可以参考Hadoop: The Definitive Guide了解其基础知识。
答案 1 :(得分:0)
在这里你可以这样做:
1)在 Mapper.setup()中初始化一个字符串向量(如果你的分割太大则初始化一个文件 - 分割大小通常是输入n HDFS的块大小)。
2)在 Mapper.map()中读取行并将它们添加到矢量中。
3)现在你在向量中有了整个分裂。你在 Mapper.cleanup()中处理:例如你可以循环遍历循环,并将每行作为键并将拆分的所有行写为reducer作为值。
答案 2 :(得分:0)
您可以在reducer任务中获取文件的所有行。如果它解决了您的问题,请查看:
public class FileLineComparison {
public static class Map extends
Mapper<LongWritable, Text, Text, Text> {
private Text fileName = new Text();
public void map(LongWritable key, Text line, Context context)
throws IOException, InterruptedException {// Parse the input string into a nice map
/*
* get file name from context and put it as key,
* so that reducer will get all lines of that file
* from one or more mappers
*/
FileSplit fileSplit = (FileSplit)context.getInputSplit();
fileName.set( fileSplit.getPath().getName());
context.write(fileName, line);
}
}
public static class Reduce extends
Reducer<Text, Text, Text, Text> {
public void reduce(Text filename, Iterable<Text> allLinesOfsinglefile, Context context) throws IOException, InterruptedException {
for (Text val : allLinesOfsinglefile) {
/*
* you get each line of the file here.
* if you want to compare each line with the rest, please loop again.
But in that case consider it as an iterable object
* do your things here
*/
}
/*
* write to out put file, if required
*/
context.write(filename, filename);
}
}
}
或者如果您真的需要它在mapper中,请在每个映射器中读取文件本身,因为我们从split
获取了文件名和路径。仅在文件大小较小时才建议它。