调用MapReduce对文件中各个单词出现次数进行统计


1.将待分析的文件(不少于10000英文单词)上传到HDFS
2.调用MapReduce对文件中各个单词出现的次数进行统计
3.将统计结果下载本地。

一.Linux的安装

这里使用VirtualBox 安装Linux的ubuntu 14.4进行操作,下载后按自己的需求安装。安装过程若下载东西很慢可以将网络断开,这样可以减少一些软件的下载,若后续需要再下。装完之后重启ubuntu,安装增强功能,开启共享文件夹与拖放,方便后续的操作。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二.准备工作

1.创建hadoop账户

首先按 ctrl+alt+t 打开终端窗口,输入如下命令创建新用户 :

sudo useradd -m hadoop -s /bin/bash

这条命令创建了可以登陆的 hadoop 用户,并使用 /bin/bash 作为 shell。

接着使用如下命令设置密码,可简单设置为 hadoop,按提示输入两次密码:

sudo passwd hadoop

可为 hadoop 用户增加管理员权限,方便部署,避免一些对新手来说比较棘手的权限问题:

sudo adduser hadoop sudo

最后注销当前用户(点击屏幕右上角的齿轮,选择注销),返回登陆界面。在登陆界面中选择刚创建的 hadoop 用户进行登陆。

2.更新apt

用 hadoop 用户登录后,我们先更新一下 apt,后续我们使用 apt 安装软件,如果没更新可能有一些软件安装不了。按 ctrl+alt+t 打开终端窗口,执行如下命令:

sudo apt-get update

安装 vim(vi增强版,基本用法相同)

sudo apt-get install vim

3.安装SSH、配置SSH无密码登陆

这里可以尝试拖放,如果可以使用拖放也可以跳过这一步,但是建议还是用SSH,因为以后会很常用。

集群、单节点模式都需要用到 SSH 登陆(类似于远程登陆,你可以登录某台 Linux 主机,并且在上面运行命令),Ubuntu 默认已安装了 SSH client,此外还需要安装 SSH server:

sudo apt-get install openssh-server

安装后,可以使用如下命令登陆本机:

 ssh localhost

此时会有如下提示(SSH首次登陆提示),输入 yes 。然后按提示输入密码 hadoop,这样就登陆到本机了。
但这样登陆是需要每次输入密码的,我们需要配置成SSH无密码登陆比较方便。
首先退出刚才的 ssh,就回到了我们原先的终端窗口,然后利用 ssh-keygen 生成密钥,并将密钥加入到授权中:

exit                           # 退出刚才的 ssh localhost
cd ~/.ssh/                     # 若没有该目录,请先执行一次ssh localhost
ssh-keygen -t rsa              # 会有提示,都按回车就可以
cat ./id_rsa.pub >> ./authorized_keys  # 加入授权

此时再用 ssh localhost 命令,无需输入密码就可以直接登陆了,如下图所示。
在这里插入图片描述

三.安装Java环境

1.安装JDK

jdk-8u162-linux-x64.tar.gz(提取码:99bg)
请把压缩格式的文件jdk-8u162-linux-x64.tar.gz下载到本地电脑,如:“/home/hpf/Downloads/”目录下
在Linux命令行界面中,执行如下Shell命令(注意:当前登录用户名是hadoop):

cd /usr/lib
sudo mkdir jvm #创建/usr/lib/jvm目录用来存放JDK文件
cd ~ #进入hadoop用户的主目录
cd Downloads  #注意区分大小写字母,刚才已经通过FTP软件把JDK安装包jdk-8u162-linux-x64.tar.gz上传到该目录下
sudo tar -zxvf ./jdk-8u162-linux-x64.tar.gz -C /usr/lib/jvm  #把JDK文件解压到/usr/lib/jvm目录下

2.验证JDK安装情况

JDK文件解压缩以后,可以执行如下命令到/usr/lib/jvm目录查看一下:

cd /usr/lib/jvm

3.设置JAVA坏境变量

cd ~
vim ~/.bashrc

通过vim编辑器。打开环境变量配置.bashrc文件,在文件开头添加如下几行内容:
(vim编辑器中,按“i”进去编辑模式,按“:wq”保存并返回终端)

export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_162
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

保存.bashrc文件并退出vim编辑器。然后,继续执行如下命令让.bashrc文件的配置立即生效:

source ~/.bashrc

验证安装情况

java -version

如果能够在屏幕上返回如下信息,则说明安装成功:
在这里插入图片描述

四.安装 Hadoop

hadoop-2.7.1.tar.gz(提取码:99bg)
使用ftp上传至下载中
在这里插入图片描述

我们选择将 Hadoop 安装至 /usr/local/ 中:

sudo tar -zxf ~/下载/hadoop-2.6.0.tar.gz -C /usr/local    # 解压到/usr/local中
cd /usr/local/
sudo mv ./hadoop-2.6.0/ ./hadoop            # 将文件夹名改为hadoop
sudo chown -R hadoop ./hadoop       # 修改文件权限

Hadoop 解压后即可使用。输入如下命令来检查 Hadoop 是否可用,成功则会显示 Hadoop 版本信息:
在这里插入图片描述

五.Hadoop伪分布式配置

1.修改配置文件

Hadoop 的配置文件位于 /usr/local/hadoop/etc/hadoop/ 中,伪分布式需要修改2个配置文件 core-site.xml 和 hdfs-site.xml 。Hadoop的配置文件是 xml 格式,每个配置以声明 property 的 name 和 value 的方式来实现。
修改配置文件 core-site.xml:

<configuration>
</configuration>

修改为下面配置:

<configuration>
    <property>
        <name>hadoop.tmp.dir</name>
        <value>file:/usr/local/hadoop/tmp</value>
        <description>Abase for other temporary directories.</description>
    </property>
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://localhost:9000</value>
    </property>
</configuration>

同样的,修改配置文件 hdfs-site.xml:

<configuration>
    <property>
        <name>dfs.replication</name>
        <value>1</value>
    </property>
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>file:/usr/local/hadoop/tmp/dfs/name</value>
    </property>
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>file:/usr/local/hadoop/tmp/dfs/data</value>
    </property>
</configuration>

2.执行 NameNode 的格式化:

cd /usr/local/hadoop
./bin/hdfs namenode -format

成功的话,会看到 “successfully formatted” 的提示。

如果在这一步时提示 Error: JAVA_HOME is not set and could not be found. 的错误,则说明之前设置 JAVA_HOME 环境变量那边就没设置好,请按教程先设置好 JAVA_HOME 变量,否则后面的过程都是进行不下去的。如果已经按照前面教程在.bashrc文件中设置了JAVA_HOME,还是出现 Error: JAVA_HOME is not set and could not be found. 的错误,那么,请到hadoop的安装目录修改配置文件“/usr/local/hadoop/etc/hadoop/hadoop-env.sh”,在里面找到“export JAVA_HOME=${JAVA_HOME}”这行,然后,把它修改成JAVA安装路径的具体地址,比如,“export JAVA_HOME=/usr/lib/jvm/default-java”,然后,再次启动Hadoop。

接着开启 NameNode 和 DataNode 守护进程。

cd /usr/local/hadoop
./sbin/start-dfs.sh  #start-dfs.sh是个完整的可执行文件,中间没有空格

若出现如下SSH提示,输入yes即可。
在这里插入图片描述

3.开启NameNode和DataNode守护进程

当程序启动完成后,可以通过命令 jps 来判断是否成功启动,若成功启动则会列出如下进程: “NameNode”、”DataNode” 和 “SecondaryNameNode”。
在这里插入图片描述

成功启动后,可以访问 Web 界面 http://localhost:50070 查看 NameNode 和 Datanode 信息,还可以在线查看 HDFS 中的文件。
在这里插入图片描述

六.调用MapReduce执行WordCount对单词进行计数

1.将待分析的文件上传到HDFS

文件命名:fpf.txt(不少于10000英文单词)
将准备好的单词文件hpff.txt上传到/home/hadoop文件夹下
在这里插入图片描述
进入hadoop目录并启动hadoop,并将hfp.txt从本机上传至 HDFS:

在这里插入图片描述
查看hdfs input中的文件,看是否存在上传的文件
在这里插入图片描述

2.安装Eclipse

在ubuntu软件中心中下载安装:
在这里插入图片描述

下载后执行如下命令,将 Eclipse 安装至 /usr/lib 目录中:

sudo tar -zxf ~/下载/eclipse-java-mars-1-linux-gtk*.tar.gz -C /usr/lib

3.安装 Hadoop-Eclipse-Plugin

要在 Eclipse 上编译和运行 MapReduce 程序,需要安装 hadoop-eclipse-plugin,可下载 Github 上的 hadoop2x-eclipse-plugin(备用下载地址:http://pan.baidu.com/s/1i4ikIoP)。

下载后,将 release 中的 hadoop-eclipse-kepler-plugin-2.6.0.jar (还提供了 2.2.0 和 2.4.1 版本)复制到 Eclipse 安装目录的 plugins 文件夹中,运行 eclipse -clean 重启 Eclipse 即可(添加插件后只需要运行一次该命令,以后按照正常方式启动就行了)。

unzip -qo ~/下载/hadoop2x-eclipse-plugin-master.zip -d ~/下载    # 解压到 ~/下载 中
sudo cp ~/下载/hadoop2x-eclipse-plugin-master/release/hadoop-eclipse-plugin-2.6.0.jar /usr/lib/eclipse/plugins/    # 复制到 eclipse 安装目录的 plugins 目录下
/usr/lib/eclipse/eclipse -clean    # 添加插件后需要用这种方式使插件生效

4.配置 Hadoop-Eclipse-Plugin

在继续配置前请确保已经开启了 Hadoop。

启动 Eclipse 后就可以在左侧的Project Explorer中看到 DFS Locations(若看到的是 welcome 界面,点击左上角的 x 关闭就可以看到了。CentOS 需要切换 Perspective 后才能看到,即接下来配置步骤的第二步)。

在这里插入图片描述
插件需要进一步的配置。

第一步:选择 Window 菜单下的 Preference。
在这里插入图片描述
此时会弹出一个窗体,窗体的左侧会多出 Hadoop Map/Reduce 选项,点击此选项,选择 Hadoop 的安装目录(如/usr/local/hadoop,Ubuntu不好选择目录,直接输入就行)。
在这里插入图片描述
第二步:切换 Map/Reduce 开发视图,选择 Window 菜单下选择 Open Perspective -> Other(CentOS 是 Window -> Perspective -> Open Perspective -> Other),弹出一个窗体,从中选择 Map/Reduce 选项即可进行切换。
在这里插入图片描述
第三步:建立与 Hadoop 集群的连接,点击 Eclipse软件右下角的 Map/Reduce Locations 面板,在面板中单击右键,选择 New Hadoop Location。
在这里插入图片描述
在弹出来的 General 选项面板中,General 的设置要与 Hadoop 的配置一致。由于我使用的Hadoop伪分布式配置,设置 fs.defaultFS 为 hdfs://localhost:9000,所以此处DFS Master 的 Port 要改为 9000。Map/Reduce(V2) Master 的 Port 用默认的即可,Location Name 随意填写。
在这里插入图片描述
配置好 General ,点击 finish,Map/Reduce Location 就创建好了。

5.在 Eclipse 中操作 HDFS 中的文件

配置好后,点击左侧 Project Explorer 中的 MapReduce Location 就能直接查看 HDFS 中的文件列表了
在这里插入图片描述

6.在 Eclipse 中创建 MapReduce 项目

点击 File 菜单,选择 New -> Project…:
选择 Map/Reduce Project,点击 Next。
在这里插入图片描述

填写 Project name 为 WordCount 即可,点击 Finish 就创建好了项目。
在这里插入图片描述

此时在左侧的 Project Explorer 就能看到刚才建立的项目了。
接着右键点击刚创建的 WordCount 项目,选择 New -> Class
需要填写两个地方:在 Package 处填写 org.apache.hadoop.examples;
在 Name 处填写 WordCount。
在这里插入图片描述

创建 Class 完成后,在 Project 的 src 中就能看到 WordCount.java 这个文件。将如下 WordCount 的代码复制到该文件中。
在eclipse上运行 wordcount程序:

package org.apache.hadoop.examples;

import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
 
public class WordCount {
    public WordCount() {
    }
 
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
//        String[] otherArgs = (new GenericOptionsParser(conf, args)).getRemainingArgs();
        String[] otherArgs=new String[]{"input","output"};
        if(otherArgs.length < 2) {
            System.err.println("Usage: wordcount <in> [<in>...] <out>");
            System.exit(2);
        }
 
        Job job = Job.getInstance(conf, "word count");
        job.setJarByClass(WordCount.class);
        job.setMapperClass(WordCount.TokenizerMapper.class);
        job.setCombinerClass(WordCount.IntSumReducer.class);
        job.setReducerClass(WordCount.IntSumReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
 
        for(int i = 0; i < otherArgs.length - 1; ++i) {
            FileInputFormat.addInputPath(job, new Path(otherArgs[i]));
        }
 
        FileOutputFormat.setOutputPath(job, new Path(otherArgs[otherArgs.length - 1]));
        System.exit(job.waitForCompletion(true)?0:1);
    }
 
    public static class IntSumReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
        private IntWritable result = new IntWritable();
 
        public IntSumReducer() {
        }
 
        public void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
            int sum = 0;
 
            IntWritable val;
            for(Iterator i$ = values.iterator(); i$.hasNext(); sum += val.get()) {
                val = (IntWritable)i$.next();
            }
 
            this.result.set(sum);
            context.write(key, this.result);
        }
    }
 
    public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable> {
        private static final IntWritable one = new IntWritable(1);
        private Text word = new Text();
 
        public TokenizerMapper() {
        }
 
        public void map(Object key, Text value, Mapper<Object, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {
            StringTokenizer itr = new StringTokenizer(value.toString());
 
            while(itr.hasMoreTokens()) {
                this.word.set(itr.nextToken());
                context.write(this.word, one);
            }
 
        }
    }
}

在运行 MapReduce 程序前,需要将 /usr/local/hadoop/etc/hadoop 中将有修改过的配置文件(如伪分布式需要 core-site.xml 和 hdfs-site.xml),以及 log4j.properties 复制到 WordCount 项目下的 src 文件夹(~/workspace/WordCount/src)中,在终端中输入下列几行内容:

cp /usr/local/hadoop/etc/hadoop/core-site.xml ~/workspace/WordCount/src
cp /usr/local/hadoop/etc/hadoop/hdfs-site.xml ~/workspace/WordCount/src
cp /usr/local/hadoop/etc/hadoop/log4j.properties ~/workspace/WordCount/src

没有复制这些文件的话程序将无法正确运行,本教程最后再解释为什么需要复制这些文件。

复制完成后,务必右键点击 WordCount 选择 refresh 进行刷新(不会自动刷新,需要手动刷新),可以看到文件结构如下所示:

在这里插入图片描述
点击工具栏中的 Run 图标,或者右键点击 Project Explorer 中的 WordCount.java,选择 Run As -> Run on Hadoop,就可以运行 MapReduce 程序了。不过由于没有指定参数,运行时会提示 “Usage: wordcount “,需要通过Eclipse设定一下运行参数。
在这里插入图片描述
右键点击刚创建的 WordCount.java,选择 Run As -> Run Configurations,在此处可以设置运行时的相关参数(如果 Java Application 下面没有 WordCount,那么需要先双击 Java Application)。切换到 “Arguments” 栏,在 Program arguments 处填写 “input output” 就可以了。
在这里插入图片描述

7.执行MapReduce的 wordcount程序进行单词统计:

在这里插入图片描述
查看output文件夹是否有运行成功后生成的文件:
在这里插入图片描述
查看运行后生成的output/part-r-00000这个文件
在这里插入图片描述
文件已将单词统计结果统计好:
在这里插入图片描述
将output文件夹下载至本地:
在这里插入图片描述
执行完查看文件:
在这里插入图片描述
在这里插入图片描述
查看part-r-00000文件:
在这里插入图片描述
也可以通过eclipse查看:
在这里插入图片描述

七.总结

本次实验使我学到了很多东西,从ubuntu,hadoop,jdk,eclipse的安装再到WordCount执行的完成,每个步骤都能使我学会一些操作、命令和知识。也更加了解了大数据这门课,对linux的命令记得更牢了。过程中也发现了很多自己的不足之处,接下去会继续学习这方面的知识。

八.参考材料

1.http://dblab.xmu.edu.cn/blog/install-hadoop/
2. http://dblab.xmu.edu.cn/blog/285/
3. http://dblab.xmu.edu.cn/blog/290-2/
4. http://dblab.xmu.edu.cn/blog/hadoop-build-project-using-eclipse/

首先,你需要编写 MapReduce 程序来对文件单词出现次数进行统计。下面是一个简单的示例程序: ```java import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.Reducer; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class WordCount { public static class TokenizerMapper extends Mapper<LongWritable, Text, Text, IntWritable>{ private final static IntWritable one = new IntWritable(1); private Text word = new Text(); public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { StringTokenizer itr = new StringTokenizer(value.toString()); while (itr.hasMoreTokens()) { word.set(itr.nextToken()); context.write(word, one); } } } public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> { private IntWritable result = new IntWritable(); public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { int sum = 0; for (IntWritable val : values) { sum += val.get(); } result.set(sum); context.write(key, result); } } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "word count"); job.setJarByClass(WordCount.class); job.setMapperClass(TokenizerMapper.class); job.setCombinerClass(IntSumReducer.class); job.setReducerClass(IntSumReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); System.exit(job.waitForCompletion(true) ? 0 : 1); } } ``` 在这个程序,`TokenizerMapper` 类将输入文件的每行按空格分割为单词,然后将每个单词作为键,将值设置为 `1`,并发射到上下文。 `IntSumReducer` 类对每个键的值进行求和,并将结果输出。 在 `main` 方法,我们设置了 Mapper 和 Reducer 类、输入和输出路径,并启动了我们的作业。 接下来,你可以通过以下步骤使用 IntelliJ IDEA 来运行该程序: 1. 打开 IntelliJ IDEA,并创建一个新项目。 2. 将上述代码复制到新项目的 `WordCount.java` 文件。 3. 点击菜单栏的 `File -> Project Structure`,在弹出的窗口选择 `Libraries`,然后点击 `+` 按钮添加 Hadoop JARs。 4. 在 `Project Structure` 窗口选择 `Artifacts`,然后点击 `+` 按钮添加一个可执行的 JAR 文件。 5. 在 `Main Class` 输入 `WordCount`,然后点击 `OK`。 6. 点击菜单栏的 `Build -> Build Artifacts`,然后选择 `Build`。 7. 在 `out/artifacts/WordCount_jar` 目录下找到生成的 JAR 文件。 8. 在命令行输入以下命令来运行程序: ``` hadoop jar WordCount.jar <input_file_path> <output_directory_path> ``` 注意,你需要将 `<input_file_path>` 替换为包含输入文件的路径,将 `<output_directory_path>` 替换为输出目录的路径。 当作业完成后,你可以在输出目录找到一个包含单词计数的文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值