【转】分析Hadoop自带WordCount例子的执行过程(3)

继续向下看:

 Option fs  =  OptionBuilder.withArgName( " local|namenode:port " )
    .hasArg()
    .withDescription(
" specify a namenode " )
    .create(
" fs " );
     opts.addOption(fs);

有一个很重要的类OptionBuilder,它才完成了充实一个Option的过程,然后经过多次调用,会将多个Option都添加到opts列表中。

看一看OptionBuilder类的withArgName()方法:

  /**
     * The next Option created will have the specified argument value 
     * name.
     *
     * 
@param  name the name for the argument value
     * 
@return  the OptionBuilder instance
     
*/
    
public   static  OptionBuilder withArgName(String name)
    {
        OptionBuilder.argName 
=  name;
        
return  instance;
    }

上面,为一个OptionBuilder的实例指定一个参数(argName)name,实际上是返回了一个具有nameOptionBuilder实例。

然后,又调用了hasArg()方法,它也是OptionBuilder类的静态方法:

   /**
     * The next Option created will require an argument value.
     *
     * 
@return  the OptionBuilder instance
     
*/
    
public   static  OptionBuilder hasArg()
    {
        OptionBuilder.numberOfArgs 
=   1 ;
        
return  instance;
    }

为刚才指定参数名的那个OptionBuilder实例设置了参数的个数,因为第一次设置,当然个数为1了。

调用withDescription()方法来设定描述信息:

  /**
     * The next Option created will have the specified description
     *
     * 
@param  newDescription a description of the Option's purpose
     * 
@return  the OptionBuilder instance
     
*/
    
public   static  OptionBuilder withDescription(String newDescription)
    {
        OptionBuilder.description 
=  newDescription;
        
return  instance;
    }

比较关键的是最后一步调用,通过调用OptionBuilder类的create()方法才真正完成了一个Option的创建:

  /**
     * Create an Option using the current settings and with 
     * the specified Option <code>char</code>.
     *
     * 
@param  opt the <code>java.lang.String</code> representation 
     * of the Option
     * 
@return  the Option instance
     * 
@throws  IllegalArgumentException if <code>opt</code> is not
     * a valid character. See Option.
     
*/
    
public   static  Option create(String opt)
                         
throws  IllegalArgumentException
    {
        
//  create the option
        Option option  =   new  Option(opt, description);

        
//  set the option properties
        option.setLongOpt(longopt);
        option.setRequired(required);
        option.setOptionalArg(optionalArg);
        option.setArgs(numberOfArgs);
        option.setType(type);
        option.setValueSeparator(valuesep);
        option.setArgName(argName);
        option.setArgPattern(argPattern, limit);

        
//  reset the OptionBuilder properties
        OptionBuilder.reset();
        
//  return the Option instance
         return  option;
    }

从上面一个Option的设置,我们可以看出来,OptionBuilder类其实是一个辅助工具,用来收集与一个Option相关的信息,从而将这些信息一次全部赋予到一个新建的Option对象上,这个对象现在具有详细的信息了。

接着,通过CommandLineParser parserparse方法,可以知道public abstract class Parser implements CommandLineParser,从抽象类Parser中找到parse的实现:

public  CommandLine parse(Options options, String[] arguments, 
                             
boolean  stopAtNonOption)
        
throws  ParseException
    {
        
return  parse(options, arguments,  null , stopAtNonOption);
    }

参数stopAtNonOption表明,如果解析过程中遇到的是一个空选项是否仍然继续解析。从前面parseGeneralOptions方法 commandLine = parser.parse(opts, args, true);可知:我们传递过来一个true

再次调用Parser类的重载成员方法parse(),如下所示,解析过程非常详细:

/**
     * Parse the arguments according to the specified options and
     * properties.
     *
     * 
@param  options the specified Options
     * 
@param  arguments the command line arguments
     * 
@param  properties command line option name-value pairs
     * 
@param  stopAtNonOption stop parsing the arguments when the first
     * non option is encountered.
     *
     * 
@return  the list of atomic option and value tokens
     *
     * 
@throws  ParseException if there are any problems encountered
     * while parsing the command line tokens.
     
*/
    
public  CommandLine parse(Options options, String[] arguments, 
                             Properties properties, 
boolean  stopAtNonOption)
        
throws  ParseException
    {
        
//  initialise members
         this .options  =  options;
        requiredOptions 
=  options.getRequiredOptions();
        cmd 
=   new  CommandLine();
        
boolean  eatTheRest  =   false ;
        
if  (arguments  ==   null )
        {
            arguments 
=   new  String[ 0 ];
        }
        List tokenList 
=  Arrays.asList(flatten( this .options, 
                                               arguments, 
                                               stopAtNonOption));
        ListIterator iterator 
=  tokenList.listIterator();
       
//  process each flattened token
         while  (iterator.hasNext())
        {
            String t 
=  (String) iterator.next();
            
//  the value is the double-dash
             if  ( " -- " .equals(t))
            {
                eatTheRest 
=   true ;
            }
            
//  the value is a single dash
             else   if  ( " - " .equals(t))
            {
                
if  (stopAtNonOption)
                {
                    eatTheRest 
=   true ;
                }
                
else
                {
                    cmd.addArg(t);
                }
            }
            
//  the value is an option
             else   if  (t.startsWith( " - " ))
            {
                
if  (stopAtNonOption  &&   ! options.hasOption(t))
                {
                    eatTheRest 
=   true ;
                    cmd.addArg(t);
                }
                
else
                {
                    processOption(t, iterator);
                }
            }
            
//  the value is an argument
             else
            {
                cmd.addArg(t);
                
if  (stopAtNonOption)
                {
                    eatTheRest 
=   true ;
                }
            }
            
//  eat the remaining tokens
             if  (eatTheRest)
            {
                
while  (iterator.hasNext())
                {
                    String str 
=  (String) iterator.next();
                    
//  ensure only one double-dash is added
                     if  ( ! " -- " .equals(str))
                    {
                        cmd.addArg(str);
                    }
                }
            }
        }
        processProperties(properties);
        checkRequiredOptions();
        
return  cmd;
    }

解析之后,返回CommandLine类的实例,从而GenericOptionsParser类的成员变量commandLine获取到了一个引用。commandLineGenericOptionsParser类的一个私有成员变量。

看一下CommandLine类的实现:

package  org.apache.commons.cli;
import  java.util.Collection;
import  java.util.HashMap;
import  java.util.Iterator;
import  java.util.LinkedList;
import  java.util.List;
import  java.util.Map;
/**  
* Represents list of arguments parsed against
* a {
@link  Options} descriptor.
*
* It allows querying of a boolean {
@link  #hasOption(String opt)},
* in addition to retrieving the {
@link  #getOptionValue(String opt)}
* for options requiring arguments.
*/
public   class  CommandLine {
    
//  不能识别的 options/arguments 
     private  List args  =   new  LinkedList();
    
/**  the processed options  */
    
private  Map options  =   new  HashMap();
    
/**  the option name map  */
    
private  Map names  =   new  HashMap();
    
/**  Map of unique options for ease to get complete list of options  */
    
private  Map hashcodeMap  =   new  HashMap();
    
/**  the processed options  */
    
private  Option[] optionsArray;
     
//  创建一个命令行CommandLine的实例。
    CommandLine()
    {
        
//  nothing to do
    }
    
//  从options这个HashMap中查看,判断是否opt已经被设置了
     public   boolean  hasOption(String opt)
    {
        
return  options.containsKey(opt);
    }
     
//  调用hasOption()方法,从options这个HashMap中查看,判断是否opt已经被设置了
     public   boolean  hasOption( char  opt)
    {
        
return  hasOption(String.valueOf(opt));
    }
    
//  根据String opt返回Option的Object类型
     public  Object getOptionObject(String opt)
    {
        String res 
=  getOptionValue(opt);
        
if  ( ! options.containsKey(opt))
        {
            
return   null ;
        }
        Object type 
=  ((Option) options.get(opt)).getType();
        
return  (res  ==   null )         ?   null  : TypeHandler.createValue(res, type);
    }
     
//  根据char opt返回Option的Object类型
     public  Object getOptionObject( char  opt)
    {
        
return  getOptionObject(String.valueOf(opt));
    }
    
//  根据指定的String opt获取Option的值
     public  String getOptionValue(String opt)
    {
        String[] values 
=  getOptionValues(opt);
        
return  (values  ==   null ?   null  : values[ 0 ];
    }
     
//  根据指定的char opt获取Option的值
     public  String getOptionValue( char  opt)
    {
        
return  getOptionValue(String.valueOf(opt));
    }
    
/**  
     * Retrieves the array of values, if any, of an option.
     *
     * 
@param  opt string name of the option
     * 
@return  Values of the argument if option is set, and has an argument,
     * otherwise null.
     
*/
    
public  String[] getOptionValues(String opt)
    {
        opt 
=  Util.stripLeadingHyphens(opt);
        String key 
=  opt;
        
if  (names.containsKey(opt))
        {
            key 
=  (String) names.get(opt);
        }
        
if  (options.containsKey(key))
        {
            
return  ((Option) options.get(key)).getValues();
        }
        
return   null ;
    }
     
//  根据指定的String opt,返回Option的值的一个数组
     public  String[] getOptionValues( char  opt)
    {
        
return  getOptionValues(String.valueOf(opt));
    }
     
//  根据指定的String opt和String defaultValue获取Option的值
     public  String getOptionValue(String opt, String defaultValue)
    {
        String answer 
=  getOptionValue(opt);
        
return  (answer  !=   null ?  answer : defaultValue;
    }
     
//  根据指定的char opt和String defaultValue获取Option的值
     public  String getOptionValue( char  opt, String defaultValue)
    {
        
return  getOptionValue(String.valueOf(opt), defaultValue);
    }
     
//  返回不能够解析的Option和参数的一个数组
     public  String[] getArgs()
    {
        String[] answer 
=   new  String[args.size()];
        args.toArray(answer);
        
return  answer;
    }
      
//  返回不能够解析的Option和参数的一个列表
     public  List getArgList()
    {
        
return  args;
    }
    
/**  
     * jkeyes
     * - commented out until it is implemented properly
     * <p>Dump state, suitable for debugging.</p>
     *
     * 
@return  Stringified form of this object
     
*/
    
public  String toString() {
        StringBuffer buf 
=   new  StringBuffer();
            
        buf.append(
" [ CommandLine: [ options:  " );
        buf.append(options.toString());
        buf.append(
"  ] [ args:  " );
        buf.append(args.toString());
        buf.append(
"  ] ] " );
            
        
return  buf.toString();
    }
    
/**
     * Add left-over unrecognized option/argument.
     *
     * 
@param  arg the unrecognised option/argument.
     
*/
    
void  addArg(String arg)
    {
        args.add(arg);
    }
   
//  向CommandLine中添加一个Option,其中Option的值(可能多个)被存储
     void  addOption(Option opt)
    {
        hashcodeMap.put(
new  Integer(opt.hashCode()), opt);
        String key 
=  opt.getKey();
        
if  (key  ==   null )
        {
            key 
=  opt.getLongOpt();
        }
        
else
        {
            names.put(opt.getLongOpt(), key);
        }
        options.put(key, opt);
    }
     
//  返回CommandLine的Option 成员表的一个迭代器
     public  Iterator iterator()
    {
        
return  hashcodeMap.values().iterator();
    }
    
//  返回处理过的Option的对象数组
     public  Option[] getOptions()
    {
        Collection processed 
=  options.values();

        
//  reinitialise array
        optionsArray  =   new  Option[processed.size()];
        
//  return the array
         return  (Option[]) processed.toArray(optionsArray);
    }
}

一个CommandLine中包含一个重要的HashMap,里面存储的是键值对,即(key, opt),通过它可以非常方便地设置和访问。

接着在parseGeneralOptions方法中调用processGeneralOptions()方法,进行处理:

processGeneralOptions(conf, commandLine);

 

 processGeneralOptions的处理过程如下:

  /**
   * Modify configuration according user-specified generic options
   * 
@param  conf Configuration to be modified
   * 
@param  line User-specified generic options
   
*/
private   void  processGeneralOptions(Configuration conf,
      CommandLine line) {
    
if  (line.hasOption( " fs " )) {
      conf.set(
" fs.default.name " , line.getOptionValue( " fs " ));
    }
    
if  (line.hasOption( " jt " )) {
      conf.set(
" mapred.job.tracker " , line.getOptionValue( " jt " ));
    }
    
if  (line.hasOption( " conf " )) {
      conf.addResource(
new  Path(line.getOptionValue( " conf " )));
    }
    
if  (line.hasOption( ' D ' )) {
      String[] property 
=  line.getOptionValues( ' D ' );
      
for ( int  i = 0 ; i < property.length - 1 ; i = i + 2 ) {
        
if  (property[i] != null )
          conf.set(property[i], property[i
+ 1 ]);
      }
    }
}

传进去一个CommandLine实例,通过CommanLine的信息,来设置Configuration conf对象。设置Configuration conf对象的目的是:为HadoopTool工作而设置的,比如WordCount这个工具,在运行开始时需要获取到Hadoop的配置信息的,这个 就需要从这里设置的Configuration conf对象来获取。

上面这个processGeneralOptions()方法,是根据CommanLine的对象,获取到所有参数值的一个数组,并返回。

到此位置,前面都是为了初始化一个GenericOptionsParser parser解析器所做的工作:

GenericOptionsParser parser  =   new  GenericOptionsParser(conf, args);

进而,可以使用 GenericOptionsParser类的实例parser 来获取Hadoop的通用参数了:

   // get the args w/o generic hadoop args
    String[] toolArgs  =  parser.getRemainingArgs();

已经具备了运行Hadoop工具的条件了,可以启动了:

      return  tool.run(toolArgs);

可以根据返回的状态码检查工具运行情况。

上面Tool tool就是我们实例化的WordCount对象,这时候才进入到WordCount实现中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 运行 Hadoop 自带wordcount 程序需要几个步骤: 1. 准备输入文件: 将要统计词频的文本文件准备好,并上传到 Hadoop 集群上。 2. 创建输入路径: 使用 Hadoop 命令行工具创建文本文件的输入路径。 3. 运行 wordcount 程序: 使用 Hadoop 命令行工具运行 wordcount 程序,并指定输入路径和输出路径。 4. 检查输出结果: 使用 Hadoop 命令行工具检查 wordcount 程序的输出结果。 具体的命令行操作可以参考Hadoop的文档。 ### 回答2: Hadoop是当今最流行的分布式计算系统之一,它能够处理海量数据并实现高效的数据分析。而WordCount则是Hadoop中最简单的MapReduce程序之一,用于统计指定文本中每个单词出现的次数。下面我将分为四个步骤来详细介绍如何运行Hadoop自带WordCount程序。 第一步,准备好Hadoop环境。首先需要下载安装好Hadoop,然后启动Hadoop的相关服务,包括NameNode、DataNode、ResourceManager、NodeManager等。最后,新建一个Hadoop用户。 第二步,将待处理的文本文件放在Hadoop文件系统中。可以使用命令hadoop fs -put命令将本地文件上传到Hadoop分布式文件系统(HDFS)中。 第三步,编写WordCount程序。在Hadoop分布式文件系统的根目录下,有一个examples目录,里面包含了范例代码。我们只需要找到WordCount的实现代码WordCount.java,将代码拷贝到自己的代码目录中,然后进行相应的修改即可。 第四步,运行WordCount程序。首先需要将代码编译成jar包,然后使用命令hadoop jar WordCount.jar WordCount /input /output来执行程序。其中,/input代表输入文件的路径,/output代表输出文件的路径。 执行完毕后,可以使用hadoop fs -cat /output/part-r-00000命令来查看统计结果。 总之,运行Hadoop自带WordCount程序虽然简单,但是涉及到了整个Hadoop环境的搭建和代码实现,需要认真仔细地操作。只有熟练掌握了这些基础知识,才能更好地理解Hadoop的分布式计算特性,并进行更加高效、复杂的数据处理和分析。 ### 回答3: Hadoop是一个基于Java的分布式计算框架,它可以将大规模数据处理任务分配到多个节点上并行处理,从而大大提高处理效率。在Hadoop中,wordcount是一个非常经典的例子,它可以统计文本中各个单词的频次。运行hadoop自带wordcount,一般可以分为以下几个步骤: 1. 准备数据 在Hadoop中,一般需要将要处理的数据放在HDFS(Hadoop分布式文件系统)中,因此首先需要将要处理的文本文件上传到HDFS中。可以使用hadoop fs -put命令将本地文件上传到HDFS中。 2. 编写MapReduce程序 在Hadoop中,MapReduce程序是实现数据处理逻辑的核心。编写MapReduce程序最基本的步骤分为两步: (1)编写Map函数:对于输入的每个键值对,Map函数会将其换成若干个键值对,并输出到Reduce函数中。在wordcount中,Map函数的输入是文本文件中的一行,处理逻辑是将这一行进行切分,然后输出每个单词及其出现次数。 (2)编写Reduce函数:Reduce函数将相同键的值合并,并输出到文件中。在wordcount中,Reduce函数的输入是Map函数输出的若干个键值对,处理逻辑是将相同单词的值合并成一个键值对,输出结果。 3. 执行MapReduce程序 执行MapReduce程序可以使用hadoop jar命令,在命令行中输入框架的jar包和配置文件,然后指定输入和输出域即可。具体命令如下: hadoop jar hadoop-mapreduce-examples.jar wordcount input output 其中,hadoop-mapreduce-examples.jar是Hadoop自带的一些示例程序的jar包;input是要处理的输入文件路径;output是输出结果的保存路径。 4. 查看结果 MapReduce程序运行完后,可以使用hadoop fs -cat命令将结果文件输出到控制台上,也可以使用hadoop fs -get命令将结果文件下载到本地查看。 总的来说,运行hadoop自带wordcount程序需要准备数据、编写MapReduce程序、执行MapReduce程序和查看结果等几个步骤。掌握这些基本的步骤后,我们可以进一步学习Hadoop和MapReduce的相关知识,实现更加复杂的数据处理任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值