java中hadoop map/reduce程序中的奇怪格式问题

java中hadoop map/reduce程序中的奇怪格式问题,java,hadoop,Java,Hadoop,我有一个csv文件,其中包含以下示例记录 | publisher | site | ad clicks | ad views | |============|====================|===========|==========| | publisher1 | www.sampleSite.com | 50 | 75 | | publisher1 | www.sampleSite2.com| 10 |

我有一个csv文件,其中包含以下示例记录

| publisher  | site               | ad clicks | ad views |
|============|====================|===========|==========|
| publisher1 | www.sampleSite.com |        50 |       75 |
| publisher1 | www.sampleSite2.com|        10 |       40 |
| publisher2 | www.newSite1.com   |       100 |      175 |
| publisher2 | www.newSite2.com   |        50 |       65 |
使用java中的map/reduce,我试图汇总每个发布者的所有广告点击和广告视图。所以输出应该是这样的

publisher1 60, 115
publisher2 150, 240
我已经编写了以下代码

import java.io.IOException;
import java.util.*;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.conf.*;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapred.*;
import org.apache.hadoop.util.*;

public class SGSClickViewStats
{
    public static class Map extends MapReduceBase implements Mapper<LongWritable, Text, Text, Text> 
    {
        int recNo = 0;
        private Text publisherName = new Text();
        private Text mapOpValue    = new Text();

        public void map(LongWritable key, Text inputs, OutputCollector <Text, Text> output, Reporter rptr) throws IOException{
            String line = inputs.toString();
            String [] fields = line.split(",");
            String pubName = formatStats(fields[0]);
            String click   = fields[2];
            String views   = fields[3];
            // ***** send stats to reducer as a string separated by :
            String value   = click+":"+views;

            mapOpValue.set(formatStats(value));
            publisherName.set(pubName);   

            output.collect(publisherName, mapOpValue);
        }

        private String formatStats(String stat) {
            while((stat.indexOf("\"") >= 0) && (stat.indexOf(",")) >= 0){
                stat = stat.replace("\"","");
                stat = stat.replace(",","");
            }
            return stat;
        }
    }

    public static class Reduce extends MapReduceBase implements Reducer< Text, Text, Text, Text >
    {
        private Text pubName = new Text();
        public void reduce(Text key, Iterator<Text> value, OutputCollector<Text, Text> oc, Reporter rptr) throws IOException {
            int views     = 0;
            int clicks    = 0;
            String val    = "";
            String opVal  = "";
            Text textOpVal= new Text();

            while(value.hasNext()){
                val = value.next().toString();

                String [] tokens = val.split(":");

                try {
                    clicks = clicks + Integer.parseInt(tokens[0]);
                    views  = views  + Integer.parseInt(tokens[1]);
                } catch (Exception e) {
                    System.out.println("This is Command HQ, code red\nError Message: "+e.getLocalizedMessage()+" Error class: "+e.getClass()+"Extra, Array length: "+tokens.length);
                }
            }           

            try {
                            // ******* want to separate stats by comma but can't !!
                opVal = Integer.toString(clicks) + ":"+ Integer.toString(views);
            } catch (Exception e) {
                System.out.println("This is Command HQ, code Yellow\nError Message: "+e.getLocalizedMessage()+" Error class: "+e.getClass());
            }
            textOpVal.set(opVal);
            oc.collect(key, textOpVal);     
        }
    }

    public static void main(String [] args) throws Exception {
        JobConf jc = new JobConf(SGSClickViewStats.class);
        jc.setJobName("SGSClickViewStats");
        jc.setOutputKeyClass(Text.class);
        jc.setOutputValueClass(Text.class);

        jc.setMapperClass(Map.class);
        jc.setReducerClass(Reduce.class);
        jc.setCombinerClass(Reduce.class);

        jc.setInputFormat(TextInputFormat.class);
        jc.setOutputFormat(TextOutputFormat.class);

        FileInputFormat.setInputPaths(jc, new Path(args[0]));
        FileOutputFormat.setOutputPath(jc, new Path(args[1]));

        JobClient.runJob(jc);
    }
}
Array length是reducer函数中tokens数组的长度,因为我正在将映射器的输出发送到reducer冒号(:)分隔的标记应该有2个元素,我在设置reducer逗号分隔的输出时看到一个元素

我参考了许多文章,但找不到答案。
我真诚地希望有人能帮助我!!:)

NumberFormatException
肯定是由
Integer.parseInt
造成的,因此在计算单击次数和视图总数时,您的错误必须在第一次尝试时出现。检查映射程序传递的输出。我很确定您在映射器中没有正确格式化字符串


编辑:为了让未来的读者明白:问题在于错误地将Reducer类也用作组合器,从而产生了与映射阶段预期不同的输出。

NumberFormatException
肯定是由
Integer.parseInt
产生的,因此,在计算单击次数和视图总数时,您的错误必须出现在第一次尝试中。检查映射程序传递的输出。我很确定您在映射器中没有正确格式化字符串


编辑:为了让未来的读者明白:问题在于,错误地将Reducer类用作组合器,从而产生了与映射阶段预期不同的输出。

为什么要将Reducer用作组合器? 当数据进入缩减阶段时,它已经是“publisher\tclicks,views”格式 我想这可能是造成问题的原因

你能评论下一行并检查一下吗

jc.setCombinerClass(Reduce.class);

你为什么用你的减速机做合路器? 当数据进入缩减阶段时,它已经是“publisher\tclicks,views”格式 我想这可能是造成问题的原因

你能评论下一行并检查一下吗

jc.setCombinerClass(Reduce.class);


错误发生在哪一行?是第一次尝试还是第二次尝试?因为NumberFormatException是由Integer.parseInt引发的。@Tudor:它出现在第一个try块中。@ThomasJungblut:epic以什么方式出现?;)错误发生在哪一行?是第一次尝试还是第二次尝试?因为NumberFormatException是由Integer.parseInt引发的。@Tudor:它出现在第一个try块中。@ThomasJungblut:epic以什么方式出现?;)我已经检查了映射器输出。它是这样的:
publisher150:75
。所以它是正确的冒号分隔。我还看到了reducer的输入,它与mapper传递的相同。如果您看到错误消息,则在输入字符串“50,75”中显示
错误。这是我在reducer中生成的错误消息。来自mapper的输入采用冒号分隔格式。那么这个
50,75
值究竟从何而来呢?我们来看看formatStats方法,它只在有斜杠和逗号时才替换。字符串中似乎只有逗号而没有斜杠。所以他可以更改和或,或者只使用replaceAll()而不使用checks.slash?不,我正在尝试替换双引号和逗号。是的,但我明白你的意思。但问题是,误差出现在减速器上。正如我在上面的评论中提到的,映射器的输出是正确的,正如预期的那样,以冒号分隔的格式。哦,很抱歉,它被转义了^。但是,mapoutput始终是reducer输入。框架之间没有转换。所以问题一定出在你的代码里。妈的,你有一个组合器。这意味着reducer代码将运行两次!尝试删除行jc.setCombinerClass(Reduce.class);我已经检查了映射器输出。它是这样的:
publisher150:75
。所以它是正确的冒号分隔。我还看到了reducer的输入,它与mapper传递的相同。如果您看到错误消息,则在输入字符串“50,75”
中显示
错误。这是我在reducer中生成的错误消息。来自mapper的输入采用冒号分隔格式。那么这个
50,75
值究竟从何而来呢?我们来看看formatStats方法,它只在有斜杠和逗号时才替换。字符串中似乎只有逗号而没有斜杠。所以他可以更改和或,或者只使用replaceAll()而不使用checks.slash?不,我正在尝试替换双引号和逗号。是的,但我明白你的意思。但问题是,误差出现在减速器上。正如我在上面的评论中提到的,映射器的输出是正确的,正如预期的那样,以冒号分隔的格式。哦,很抱歉,它被转义了^。但是,mapoutput始终是reducer输入。框架之间没有转换。所以问题一定出在你的代码里。妈的,你有一个组合器。这意味着reducer代码将运行两次!尝试删除行jc.setCombinerClass(Reduce.class);是的,也是同样的问题。我去掉了那个部分,就完成了。谢谢你的帮助!是的,也是同样的问题。我去掉了那个部分,就完成了。谢谢你的帮助!