词频统计

1.需求:读取指定目录的数据,并且实现单词计数功能

2.实现方案:

Spout用于读取指定文件夹(目录),读取文件,将文件的每一行发射到Bolt

SplitBolt用于接收Spout发射过来的数据,并拆分,发射到CountBolt

CountBolt接收SplitBolt发送的每一个单词,进行单词计数操作

3.拓扑设计:

DataSourceSpout + SplitBolt + CountBolt

代码如下:

package com.csylh;

import org.apache.commons.io.FileUtils;
import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.TopologyBuilder;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.topology.base.BaseRichSpout;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Tuple;
import org.apache.storm.tuple.Values; import java.io.File;
import java.io.IOException;
import java.util.*; /**
* Description:使用Storm完成词频统计功能
*
* @author: 留歌36
* Date:2018/9/4 9:28
*/
public class LocalWordCountStormTopology {
/**
* 读取数据并发送到Bolt上去
*/
public static class DataSourceSpout extends BaseRichSpout{
//定义一个发射器
private SpoutOutputCollector collector; /**
* 初始化方法 只是会被调用一次
* @param conf 配置参数
* @param context 上下文
* @param collector 数据发射器
*/
@Override
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
//对上面定义的的发射器进行赋初值
this.collector = collector;
} /**
* 用于数据的产生
* 业务:
* 1.读取指定目录的文件夹下的数据
* 2.把每一行数据发射出去
*/
@Override
public void nextTuple() {
// 获取所有文件,这里指定文件的后缀
Collection<File> files = FileUtils.listFiles(new File("E:\\StormText"),new String[]{"txt"},true);
// 循环遍历每一个文件 ==> 由于这里指定的是文件夹下面的目录 所以就是需要进行循环遍历
for( File file : files){
try {
// 获取每一个文件的每一行
List<String> lines = FileUtils.readLines(file);
for(String line : lines){
// 把每一行数据发射出去
this.collector.emit(new Values(line));
}
//TODO 数据处理完毕之后 改名 否则的话 会一直执行的
FileUtils.moveFile(file,new File(file.getAbsolutePath()+System.currentTimeMillis())); } catch (IOException e) {
e.printStackTrace();
}
} } /**
* 声明输出字段名称
* @param declarer
*/
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("line"));
}
}
/**
* 对Spout发送过来的数据进行分割
*/
public static class SplitBolt extends BaseRichBolt{
private OutputCollector collector;
/**
* 初始化方法 只是会被执行一次
* @param stormConf
* @param context
* @param collector Bolt的发射器,指定下一个Bolt的地址
*/
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
} /**
* 用于获取Spout发送过来的数据
* 业务逻辑
* spout发送过来的数据是一行一行的line
* 这里是需要line进行分割
*
* @param input
*/
@Override
public void execute(Tuple input) {
String line = input.getStringByField("line");
String[] words = line.split(","); for(String word : words){
// 这里把每一个单词发射出去
this.collector.emit(new Values(word));
}
} @Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
/**
* 词频汇总的Bolt
*/
public static class CountBolt extends BaseRichBolt{
/**
* 由于这里是不需要向外部发射 所以就不需要定义Collector
* @param stormConf
* @param context
* @param collector
*/
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
}
Map<String,Integer> map = new HashMap<String, Integer>();
/**
* 业务逻辑
* 1.获取每一个单词
* 2.对每一个单词进行汇总
* 3.输出结果
* @param input
*/
@Override
public void execute(Tuple input) {
// 获取每一个单词
String word = input.getStringByField("word");
Integer count = map.get(word);
if (count == null){
count = 0;
}
count++;
// 对单词进行汇总
map.put(word,count);
// 输出
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~");
Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
for(Map.Entry<String,Integer> entry :entrySet){
System.out.println(entry);
}
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
}
/**
* 主函数
* @param args
*/
public static void main(String[] args) {
// 使用TopologyBuilder根据Spout和Bolt构建Topology
TopologyBuilder builder = new TopologyBuilder();
// 设置Bolt和Spout 设置Spout和Bolt的关联关系
builder.setSpout("DataSourceSpout",new DataSourceSpout());
builder.setBolt("SplitBolt",new SplitBolt()).shuffleGrouping("DataSourceSpout");
builder.setBolt("CountBolt",new CountBolt()).shuffleGrouping("SplitBolt");
// 创建一个本地的集群
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("LocalWordCountStormTopology",new Config(),builder.createTopology());
}
}

小结:开发Storm程序的步骤就是:

根据需求 设计实现方案 规划拓扑

一般是先写Spout数据产生器 发射数据到Bolt

接着,就是Bolt进行数据处理,如果有多个Bolt,非最后一个Bolt也要写发射器Collector

最后一个Bolt直接输出结果或者 输出到HDFS或者关系型数据库中

最终需要将Spout和Bolt进行组装起来(借助TopologyBuilder)

使用Storm进行词频统计的更多相关文章

  1. Storm- 使用Storm实现词频汇总

    需求:读取指定目录的数据,并实现单词计数的功能 实现方案: Spout来读取指定目录的数据,作为后续Bolt处理的input 使用一个Bolt把input 的数据,切割分开,我们按照逗号进分割 使用一 ...

  2. 使用storm分别进行计数和词频统计

    计数 直接上代码 public class LocalStormSumTopology { public static void main(String[] agrs) { //Topology是通过 ...

  3. python瓦登尔湖词频统计

    #瓦登尔湖词频统计: import string path = 'D:/python3/Walden.txt' with open(path,'r',encoding= 'utf-8') as tex ...

  4. 作业3-个人项目<词频统计>

    上了一天的课,现在终于可以静下来更新我的博客了.       越来越发现,写博客是一种享受.来看看这次小林老师的“作战任务”.                词频统计 单词: 包含有4个或4个以上的字 ...

  5. C语言实现词频统计——第二版

    原需求 1.读取文件,文件内包可含英文字符,及常见标点,空格级换行符. 2.统计英文单词在本文件的出现次数 3.将统计结果排序 4.显示排序结果 新需求: 1.小文件输入. 为表明程序能跑 2.支持命 ...

  6. c语言实现词频统计

    需求: 1.设计一个词频统计软件,统计给定英文文章的单词频率. 2.文章中包含的标点不计入统计. 3.将统计结果以从大到小的排序方式输出. 设计: 1.因为是跨专业0.0···并不会c++和java, ...

  7. 软件工程第一次个人项目——词频统计by11061153柴泽华

    一.预计工程设计时间 明确要求: 15min: 查阅资料: 1h: 学习C++基础知识与特性: 4-5h: 主函数编写及输入输出部分: 0.5h: 文件的遍历: 1h: 编写两种模式的词频统计函数: ...

  8. Hadoop上的中文分词与词频统计实践 (有待学习 http://www.cnblogs.com/jiejue/archive/2012/12/16/2820788.html)

    解决问题的方案 Hadoop上的中文分词与词频统计实践 首先来推荐相关材料:http://xiaoxia.org/2011/12/18/map-reduce-program-of-rmm-word-c ...

  9. pyspark进行词频统计并返回topN

    Part I:词频统计并返回topN 统计的文本数据: what do you do how do you do how do you do how are you from operator imp ...

随机推荐

  1. IT人不仅要提升挣钱能力,更要拓展挣钱途径

    前几天我上班路上,和小区门口开车的师傅闲聊,发现他们虽然学历不高,但挣钱的途径不少,比如固定接送多位客户,然后能通过朋友圈拓展新客户,而且通过客户口口相传,也能不断拉到生意,算下来每月也能挣1万5出头 ...

  2. Kibana 管理界面使用教程

    使用浏览器访问 ip:5601 默认端口,进入首页 Discover:日志管理视图 Visualize:统计视图 Dashboard:仪表视图 Timelion:时间轴视图 APM:性能管理视图 De ...

  3. js加密后台加密解密以及验证码

    该文档为转载内容: 加密解密 1 前端js加密概述 2 前后端加密解密 21 引用的js加密库 22 js加密解密 23 Java端加密解密PKCS5Padding与js的Pkcs7一致 验证码 1 ...

  4. Docker学习总结(三)--常用命令

    镜像相关命令 查看镜像 docker images 返回列表字段含义如下: 字段名称 字段含义 REPOSITORY 镜像名称 TAG 镜像标签 IMAGE ID 镜像 ID CREATED 镜像创建 ...

  5. ECMAScript---数字类型详解

    number数字类详解 整数.小数.负数.NaN都是number数字类型的 NaN:not a number ,但是它是数字类型的 isNaN:检测当前值是否 不是有效数字,返回true代表不是有效数 ...

  6. Leetcode之深度优先搜索(DFS)专题-515. 在每个树行中找最大值(Find Largest Value in Each Tree Row)

    Leetcode之深度优先搜索(DFS)专题-515. 在每个树行中找最大值(Find Largest Value in Each Tree Row) 深度优先搜索的解题详细介绍,点击 您需要在二叉树 ...

  7. [Mysql] GroupBy 分组,按天、周、月

    简单说明: 最近在做报表功能的时候,需要将数据按天.周和月进行合并展示(数据记录都是按天20190701). 正文: 说明:数据表中date都是int类型:如 20190701 一.按天 SELECT ...

  8. MySQL运行时自动生成的性能相关的数据参考

      某大师曾说过,一个DBA要像熟悉自己的老婆一样熟悉自己的数据库,个人认为包含了两个方面的熟悉: 1,在稳定性层面来说,更多的是关注高可用.读写分离.负载均衡,灾备管理等等high level层面的 ...

  9. javaScript 基础知识汇总(六)

    1.基本类型与对象的区别 基本类型:是原始类型的中的一种值. 在JavaScript中有6中基本类型:string number  boolean  symbol  null  undefined 对 ...

  10. 天梯杯 PAT L2-013 红色警报

    战争中保持各个城市间的连通性非常重要.本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报.注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不 ...