词频统计的java实现方法——第一次改进
需求概要
原需求
1.读取文件,文件内包可含英文字符,及常见标点,空格级换行符。
2.统计英文单词在本文件的出现次数
3.将统计结果排序
4.显示排序结果
新需求:
1.小文件输入. 为表明程序能跑
2.支持命令行输入英文作品的文件名
3. 支持命令行输入存储有英文作品文件的目录名,批量统计。
4. 从控制台读入英文单篇作品
程序输入:
1.控制台输入文本
2.英文文本文件
3.英文目录,目录下包含单个或多个英文文本文件
程序输出:
1.英文单词在本文件或控制台输入中的出现的次数,按出现次数排序
2.文本或控制台输入文字的单词数和不重复单词数
输出位置:
控制台或指定文件
支持统计的词包括:纯英文单词和字母开头夹杂数字的单词,例如:happy,x11,i386,w3c等
程序的使用设计
1.程序直接运行,不加参数,则进入标准输入状态,所有标准输入作为词频统计分析的内容,windows下回车加ctrl+Z作为退出输入模式的出口,然后对输入缓存进行统计
2.使用选项参数
默认情况下接受文件名或文件夹作为输入,读入单独或文件夹下的多个文件
-o可以指定输出文件名,即保存统计结果到文件中,不适用-o选项则将输出结果打印到终端或控制台,
-s出现此选项则将之后的输入视为标准输入,作为分析的内容。
主要功能设计和分析
前一部分的内容不在此赘述,以下为更新后的功能设计
不同输入逻辑处理
根据最新需求,本程序需要处理来自文本和控制台的输入,需要对程序运行的参数和方法进行控制,java程序的main函数String[] args可以接收程序运行的参数,当参数为空时则进入标准输入读入的模式,有参数的时候根据不同参数进行操作。
为简化逻辑,参数的读入和初始化可以建立初始化器来使用的参数进行环境设置或者初始化,main函数中则根据已经设定好的环境来决定从哪读入向哪输出。
缓冲读取文件或标准输入流,统计词频
当程序参数为空时需要将标准输入作为待分析内容,java提供的System.in可作为标准输入,读入时可以使用byte[]来接收。
当程序读入文件时可以使用char[]来接收读取到的内容,这与标准输入流略有不同,不过可以通过类型转换的方式来实现重用。
词频统计与之前的区别在于,使用BufferedReader提供的read来替换readline来解决当行过长导致的字符串溢出问题,这样就需要定义一个缓冲区来分块读取文件或输入流的内容,读取到的缓冲区再模仿状态机的处理方式来确定读入的字符该如何处理
多文件的读取
java文件类提供判断一个路径是不是文件夹的函数即File.isDirectory(),如果确定输入为文件夹则使用File.listFiles()获取到文件夹下的所有文件,然后循环分析词频,根据已经创建好的环境决定输出到文件还是控制台。
部分代码实现
初始化器实现
String inputFile = null;
String outputFile = null;
boolean stdin = false; private boolean setArgs(String[] args) {
try {
if (args.length == 0) {
stdin=true;
return true;
}
boolean isOption = false;
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("-")) {
isOption = true;
if (args[i].equals("-o")) {
outputFile = args[i + 1];
} else if(args.equals("-s")){
stdin = true;
return true;
}else{
System.out.println("unknow commend:" + args[i]);
return false;
}
} else if (isOption) {
// setOpetion
isOption = false;
} else if (inputFile == null) {
inputFile = args[i];
} else {
System.out.println("wrong command");
return false;
}
}
System.out.println("inputfile = " + inputFile);
System.out.println("onputfile = " + outputFile);
if (inputFile == null) {
System.out.println("no input file name");
return false;
}
} catch (Exception e) {
System.out.println("wrong command");
return false;
}
return true;
}
更新后的词频统计
文件方式作为输入
public Map<String, Integer> getWordGroupCountBuffered(String filename) {
try {
FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
StringBuffer content = new StringBuffer("");
Map<String, Integer> result = new HashMap<String, Integer>();
char[] ch = new char[64];
int bs = 0;
int idx;
boolean added = false;
total = 0;
while ((bs = br.read(ch)) > 0) {
for (idx = 0; idx < bs; idx++) {
if (isCharacter(ch[idx])==1) {
content.append(ch[idx]);
added = false;
} else if(isCharacter(ch[idx])==2){
if(added == true){
continue;
}else{
content.append(ch[idx]);
}
} else {
if(added==true){
continue;
}
added = true;
if(content.equals(""))
continue;
String key = content.toString();
if (result.containsKey(key))
result.put(key, result.get(key) + 1);
else
result.put(key, 1);
total++;
content = new StringBuffer("");
continue;
}
}
}
br.close();
fr.close();
return result;
} catch (FileNotFoundException e) {
System.out.println("failed to open file:" + filename);
e.printStackTrace();
} catch (Exception e) {
System.out.println("some expection occured");
e.printStackTrace();
}
return null;
}
标准输入作为输入
public Map<String, Integer> getWordGroupCountBuffered(InputStream in) {
try {
StringBuffer content = new StringBuffer("");
Map<String, Integer> result = new HashMap<String, Integer>();
byte[] bt = new byte[128];
char [] ch = new char[64];
int bs = 0;
int idx;
int cs = 0;
boolean added = false;
total = 0;
while ((bs = in.read(bt)) > 0) {
ch = byteToChar(bt,bs);
cs = bs;
for (idx = 0; idx < cs; idx++) {
if (isCharacter(ch[idx])==1) {
content.append(ch[idx]);
added = false;
} else if(isCharacter(ch[idx])==2){
if(added == true){
continue;
}else{
content.append(ch[idx]);
}
} else {
if(added==true){
continue;
}
added = true;
if(content.equals(""))
continue;
String key = content.toString();
if (result.containsKey(key))
result.put(key, result.get(key) + 1);
else
result.put(key, 1);
total++;
content = new StringBuffer("");
continue;
}
}
}
return result;
} catch (Exception e) {
System.out.println("some expection occured");
e.printStackTrace();
}
return null;
}
文件夹下多文件统计函数头为
public void printSortedWordGroupCountToFileBuffered(File[] files, String destinationFilename)
实现方式基本同单个文件统计方式,仅需添加循环遍历和输出文件方式设定为追加,并且第一次打开时清空文件内容,防止多次执行同一命令时重复追加到一个文件。
主函数逻辑控制
public static void main(String[] args) {
RunFileWordUtil rfu = new RunFileWordUtil();
if (!rfu.setArgs(args)) {
return;
}
File f = null;
FileWordUtil fu = new FileWordUtil();
if(rfu.stdin){
fu.printSortedWordGroupCountBuffered(System.in);
}else{
f = new File(rfu.inputFile);
if(f.isDirectory()){
File[] files = f.listFiles();
if(rfu.outputFile == null){
System.err.println("warning : print to console is not recomanded");
fu.printSortedWordGroupCountBuffered(files);
}else{
fu.printSortedWordGroupCountToFileBuffered(files,rfu.outputFile);
}
}else if (rfu.outputFile == null) {
System.err.println("warning : print to console is not recomand");
fu.printSortedWordGroupCountBuffered(rfu.inputFile);
}else {
fu.printSortedWordGroupCountToFileBuffered(rfu.inputFile, rfu.outputFile);
}
}
}
其他被调用的部分自定义函数
private int isCharacter(char ch) {
if ((ch >= 'a' && ch <= 'z'))
return 1;
if((ch >= 'A' && ch <= 'Z'))
return 1;
if(ch>='0'&&ch<='9')
return 2;
return 0;
}
private char[] byteToChar(byte[] bt,int length){
char[] ch = new char[length];
for(int i=0;i<length;i++){
ch[i]=(char)bt[i];
}
return ch;
}
实际运行结果
1.标准输入作为输入内容

2.单个文件作为输入内容
文件内容:
hello world
this is a
what a sunny day!
do
you
have a cup? read the book My English is very very pool.
warning为标准错误输出,在支持彩色显示的终端中可以显示为红色(或其他自定义颜色)

3.文件夹下的所有文件作为输入内容

4.结果输出到文件

5.大文件统计:
文件内容:英文版WarandPeace.txt

工程地址:https://coding.net/u/jx8zjs/p/wordCount/git
ssh://git@git.coding.net:jx8zjs/wordCount.git
词频统计的java实现方法——第一次改进的更多相关文章
- 效能分析——词频统计的java实现方法的第一次改进
java效能分析可以使用JProfiler 词频统计处理的文件为WarAndPeace,大小3282KB约3.3MB,输出结果到文件 在程序本身内开始和结束分别加入时间戳,差值平均为480-490ms ...
- 英文词频统计的java实现方法
需求概要 1.读取文件,文件内包可含英文字符,及常见标点,空格级换行符. 2.统计英文单词在本文件的出现次数 3.将统计结果排序 4.显示排序结果 分析 1.读取文件可使用BufferedReader ...
- C# 词频统计 东北师范大学 软件项目管理 第一次作业
一.作为杨老师的学生第一次听杨老师讲课,印象最深的就是:工程中所有步骤之间是乘法,如果任何一步为0,工程就做不出来了.以前所有老师讲到的都是不要太在乎结果,努力的过程很重要,但是这在软件工程中不合适了 ...
- 软件工程第一次个人项目——词频统计by11061153柴泽华
一.预计工程设计时间 明确要求: 15min: 查阅资料: 1h: 学习C++基础知识与特性: 4-5h: 主函数编写及输入输出部分: 0.5h: 文件的遍历: 1h: 编写两种模式的词频统计函数: ...
- 【第二周】Java实现英语文章词频统计(改进1)
本周根据杨老师的spec对英语文章词频统计进行了改进 1.需求分析: 对英文文章中的英文单词进行词频统计并按照有大到小的顺序输出, 2.算法思想: (1)构建一个类用于存放英文单词及其出现的次数 cl ...
- Java实现的词频统计——功能改进
本次改进是在原有功能需求及代码基础上额外做的修改,保证了原有的基础需求之外添加了新需求的功能. 功能: 1. 小文件输入——从控制台由用户输入到文件中,再对文件进行统计: 2.支持命令行输入英文作品的 ...
- java词频统计——改进后的单元测试
测试项目 博客文章地址:[http://www.cnblogs.com/jx8zjs/p/5862269.html] 工程地址:https://coding.net/u/jx8zjs/p/wordCo ...
- USTC《现代软件工程》春季学期——第一次个人作业:词频统计
截止日期 2018年3月29日23:59 要求 1. 对源文件(*.txt,*.cpp,*.h,*.cs,*.html,*.js,*.java,*.py,*.php等,文件夹内的所有文件)统计字符数. ...
- 词频统计 ——Java
github地址 :https://github.com/NSDie/personal-project 一.计划表 PSP2.1 Personal Software Process Stages 预估 ...
随机推荐
- 从OEL5中启动简单的dns服务
在OEL5中,有一个 dnsmasq,可以适合小型的实验性的dns设置. 如果可以看到类似如下的内容,说明dnsmasq已经设置好了. [root@dnssvr ~]# rpm -qa dnsmasq ...
- centos7 安装postgres9.4
1.安装postgres资源:> yum install https://download.postgresql.org/pub/repos/yum/9.4/redhat/rhel-7-x86_ ...
- Bootstrap学习笔记(3)--表格\表单\图片
Bootstrap表格 表格类: .table只会在表行之间增加横线; .table-striped会在表格行之间增减斑马线; .table-hover会给表设置鼠标悬停状态; ...
- 如何实现Canvas图像的拖拽、点击等操作
上一篇Canvas的博文写完后,有位朋友希望能对Canvas绘制出来的图像进行点击.拖拽等操作,因为Canvas绘制出的图像能很好的美化.好像是想做炉石什么的游戏,我也没玩过. Canvas在我的理解 ...
- Linux命令对应的英文及整体学习法
linux命令 注意一下内容收集与互联网,如果觉得有版权问题,请联系. 用Linux命令的时候,如果熟悉对应英文的含义,更有助于理解相应的命令.man: Manual 意思是手册,可以用这个命令查询其 ...
- [算法总结] 20 道题搞定 BAT 面试——二叉树
本文首发于我的个人博客:尾尾部落 0. 几个概念 完全二叉树:若二叉树的高度是h,除第h层之外,其他(1~h-1)层的节点数都达到了最大个数,并且第h层的节点都连续的集中在最左边.想到点什么没?实际上 ...
- RHEL7 利用单个物理网卡实现VLAN
使用nmcli创建网桥配置 #nmcli connection add type bridge con-name br0 stp no 使用nmcli创建VLAN设备配置 #nmcli connect ...
- SparkRDD编程实战
通过spark实现点击流日志分析案例 1. 访问的pv package cn.itcast import org.apache.spark.rdd.RDD import org.apache.spar ...
- cmd下执行mysql
1. mysql -uroot -p1234; 2. show databases; 3. use testnode; 4. 创建数据库表 CREATE DATABASE `node` DEFA ...
- Django_cookie+session
一.cookie和session介绍 cookie 由服务器产生内容,浏览器收到请求后保存在本地:当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是“谁 ...