hadoop入门基础两种方式进行词频统计及常见错误解决

目录

一 、hadoop本地运行环境的配置。

错误提示:

二  程序的编写

错误提示:

错误提示:

三 运行

本地运行:

错误提示:

集群运行

错误提示:

错误提示:

​编辑

完结~散花~


本文出现的错误及解决方法均为亲身经历,太痛苦了....

在此将错误整理一下,供大家避坑。

首先hadoop的运行方式分为本地运行和集群运行,本机运行及在本机编写程序后直接执行,集群运行则是将程序写完后打包,上传到hdfs中运行。

一 、hadoop本地运行环境的配置。

hadoop的运行需要jdk的安装并配置,本文主要讲hadoop的配置,java环境没有配的请一并配置java环境。

下载hadoop,进入官网选择适合的版本并解压。

我在此放入我的hadoop版本需要的可以提

https://pan.baidu.com/s/1V0-Vo7ruScsKcaMb-gH_5A?pwd=9629 
提取码:9629 

hadoop解压后还需要在bin目录下放入winutils.exe和hadoop.dll才能保证程序的正常运行。

尽量放入和hadoop版本一样的文件,这是我的版本文件,需要的可以自提。

十亿少年的梦/hadoop - 码云 - 开源中国 (gitee.com)

成功放入后如图

环境变量的配置

输入win+R,输入sysdm.cpl,高级-->环境变量-->添加hadoop的系统环境变量

进去点击Path进入编辑环境变量界面

添加hadoop环境变量

点击CLASSPATH,如图

配置完成后,点击三次确定,打开cmd窗口,输入java -version 和 hadoop -version,如图所示

显示正确的版本信息及说明环境变量配置成功,

错误提示:

如果在此显示失败,则尝试在编辑环境变量的页面将hadoop和java的环境变量放在最上面后,重新尝试。

注意在hadoop的路径和java的路径下不要使用有空格或者中文出现,否则也会报错。

二  程序的编写

打开idea创建maven项目,配置依赖。

pom.xml

<dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>3.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>3.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.3.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        
    </dependencies>

并在recources下创建log4j.properties文件,写入一下内容

log4j.rootLogger=debug, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log

log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=5

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

错误提示:

如果不进行log4j依赖的配置则会出现:

log4j警告之log4j:WARN No appenders could be found for logger(org.apache.ibatis.logging.LogFactory).的错误。

在src-->main-->java下创建WordCount包,并在包下分别创建WordcountMapper.Class、WordCountReducer.Class、WordCountDriver.Class文件,内容如下:

WordCountDriver.Class

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCountDriver {
    public static void main(String[] args) throws Exception{
        Configuration conf = new Configuration();
        //本地运行
        conf.set("mapreduce.framework.name","local");
        //集群中运行
//        conf.set("mapreduce.framework.name","yarn");
        Job job = Job.getInstance(conf);
        //2:获取jar包信息
        job.setJarByClass(WordCountDriver.class);
        //3:关联自定义的mapper和reducer
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);
        //4:设置map输出类型数据
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);
        //5:设置最终输出数据类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        //本地运行路径
        FileInputFormat.setInputPaths(job,new Path("D:/input"));
        FileOutputFormat.setOutputPath(job,new Path("D:/input/output"));

        //集群运行路径
//        FileInputFormat.setInputPaths(job, new Path(args[0]));
//        FileOutputFormat.setOutputPath(job,new Path(args[1]));



        // 提交job
        boolean flag = job.waitForCompletion(true);

        //成功后退出
        System.exit(flag ? 0 : -1);
    }
}

WordCountMapper.Class

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

/**
 * description:
 * KEYIN: Map任务读数据的key类型,offset,是每行数据起始位置的偏移量,Long
 * VALUEIN:Map任务读数据的value类型,其实就是一行行的字符串,String
 * Deer Bear River
 * KEYOUT: map方法自定义实现输出的key的类型,String
 * VALUEOUT: map方法自定义实现输出的value的类型,Integer
 *词频统计:相同单词的次数   (Deer,1)
 *
 * Long,String,String,Integer是Java里面的数据类型
 * Hadoop自定义类型:序列化和反序列化
 * LongWritable,Text
 *
 * date: 2021/10/5 12:24 <br>
 * author: Neal <br>
 * version: 1.0 <br>
 */
public class WordCountMapper extends Mapper<LongWritable, Text,Text, IntWritable> {

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        // 把value对应的行数据按照指定的分隔符拆开
        String[] words = value.toString().split(" ");
        // 将每个字符串放入上下文中
        for (String word : words) {
            context.write(new Text(word),new IntWritable(1));
        }
    }
}

WordCountReducer.Class

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;
import java.util.Iterator;

/**
 * description:
 * (Deer,1)  (Bear,1) (River,1)
 *
 * map的输出到reduce端,是按照相同的key分发到一个reduce上去执行 可参考上面的图解
 *
 * reduce1: (Car,1)(Car,1)(Car,1)  ==> (Car, <1,1,1>)
 * reduce2: (Deer,1)(Deer,1)  ==> (Deer, <1,1>)
 * reduce3: (River,1)(River,1)  ==> (River, <1,1>)
 * reduce4: (Beer,1)(Beer,1)  ==> (Beer, <1,1>)
 *
 * Reducer和Mapper中使用到了模板设计模式
 * date: 2021/10/5 12:28 <br>
 * author: Neal <br>
 * version: 1.0 <br>
 */
public class WordCountReducer extends Reducer<Text, IntWritable,Text,IntWritable> {

    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        int count = 0;
        Iterator<IntWritable> it = values.iterator();
        while(it.hasNext()) {
            IntWritable value = it.next();
            count += value.get();
        }
        context.write(new Text(key),new IntWritable(count));
    }
}

WordCountDriver.Class文件中有本地运行和集群运行两种方式,首先进行本地运行,注意修改为自己的text.txt路径。

错误提示:

output文件在运行前要保证不存在,否则会出现already exist 错误。

保证input文件夹下有文件,并且路径要写对。

三 运行
本地运行:

三个类写好后,先进行本地运行,控制台出现

则表示运行成功。找到对应的output文件查看运行结果。

错误提示:

程序是没有任何问题的,如果出现错误则说明可能是以上一个步骤没有配置好,请仔细检查。

如果出现运行成功但是,没有output文件,则说明上面的一个步骤没有执行好,检查一下环境变量的配置,不要出现空格和中文,导入的包一定要是下载的依赖里的。

集群运行

在本地成功运行后,保证程序是没有问题的对项目进行打包,进行集群运行。

将WordCountDriver.Class文件下的集群运行的方式和路径的注释放开,将本地运行的方式和路径进行注释。(即只需要修改这两个地方即可)

找到屏幕右边MAVEN--> 生命周期-->package,双击package进行打包。

运行成功后,在控制台的提示信息里找到对应的tar文件。

打开hadoop虚拟机,并开始集群,打开hdfs的web界面。

切换到你的用户hdfs用户下

su hadoop01  //hadoop01 是我的用户名,你的可能不是,请自行修改
错误提示:

一定要先切换用户在创建文件夹,否则将会因为权限问题报错。

 Permission denied: user=root, access=EXECUTE, inode="/tmp":hadoop01:supergroup:drwx------

通过xftp或者s输入sudo rz命令将打包好的jar和准备好的text.txt文件文件传到虚拟机上。

创建在hdfs上创建input目录,将text.txt文件上传到input目录下。可以通过web界面查看。

hdfs dfs -mkdir /input
hdfs dfs -put text.txt /input
错误提示:

修改input文件夹的权限,保证hadoop01 用户对input有执行的权限。不修改还是会报错++++

到此,你就可以真正的运行了,执行命令

hadoop jar hadoop_api-1.0-SNAPSHOT.jar wordCount.WordCountDriver /input /output

结果显示如下,则运行成功

通过cat查看也可以在web界面查看。

到此,两种运行方式,实现词频统计结束。

完结~散花~


  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个简单的 Hadoop 单词统计代码示例,统计一个文本文件中每个单词出现次数: Mapper 类: ``` import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Mapper; public class WordCountMapper 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 { String line = value.toString(); StringTokenizer tokenizer = new StringTokenizer(line); while (tokenizer.hasMoreTokens()) { word.set(tokenizer.nextToken()); context.write(word, one); } } } ``` Reducer 类: ``` import java.io.IOException; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> { public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { int sum = 0; for (IntWritable val : values) { sum += val.get(); } context.write(key, new IntWritable(sum)); } } ``` Driver 类: ``` 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.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class WordCountDriver { public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "word count"); job.setJarByClass(WordCountDriver.class); job.setMapperClass(WordCountMapper.class); job.setCombinerClass(WordCountReducer.class); job.setReducerClass(WordCountReducer.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); } } ``` 在运行时,需要将输入文件和输出目录作为参数传递给程序。例如: ``` $ hadoop jar WordCount.jar WordCountDriver /input /output ``` 其中,`/input` 是输入文件所在目录,`/output` 是输出目录。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十亿少男的梦421

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值