词频统计的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 预估 ...
随机推荐
- wp apps
WP apps: 明星脸 用于 Windows 10 的 URL https://www.microsoft.com/store/apps/9nblggh5kq63 用于 Windows Phone ...
- Deep Learning综述[下]
Image understanding with deep convolutional networks 直到2012年ImageNet大赛之前,卷积神经网络一直被主流机器视觉和机器学习社区所遗弃.2 ...
- 为firefox添加flash插件
需要自行下载flash for firefox进行安装,安装后即可看到 Shockwave Flash 插件
- [BZOJ4883][Lydsy1705月赛]棋盘上的守卫[最小基环树森林]
题意 有一大小为 \(n*m\) 的棋盘,要在一些位置放置一些守卫,每个守卫只能保护当前行列之一,同时在每个格子放置守卫有一个代价 \(w\) ,问要使得所有格子都能够被保护,需要最少多少的代价. \ ...
- Permission Policies
The Permission Policy determines Security System behavior when there are no explicitly specified per ...
- python中变量的数据类型总结
1.变量的数据类型,分为数值型和非数值型 数值型: int(整型) float(浮点型) bool (布尔型,只有True和Flase) compex(复数型, 用于科学计算) 非数值型: str(字 ...
- 如何在unix系统中用别的用户运行一个程序?
1.问题的缘由 实际开发系统的时候,经常需要用别的用户运行一个程序.比如,有些系统为保证系统安全,不允许使用root来运行.这里,我们总结了unix系统下如何解决这个问题的一些方法.同时,我们还讨论如 ...
- 前端开发利器 livereload -- 从此告别浏览器F5键
各位从事前端开发的童鞋们,大家每天coding && coding,然后F5 && F5,今天推荐一个静态文件在浏览器中自动更新的扩展 livereload,不同手动刷 ...
- docker usage
docker ps -a 查看物理机上面所有容器信息列表 docker exec -it $docker_id /bin/bash 进入容器以默认帐号 docker exec -it -u root ...
- Openstack逻辑架构
一. Keystone -身份认证管理 提供了认证和授权的服务,openstack不同的组件通信都要经过授权,确保正确的用户和服务是经过认证的.并且它集成了大量的认证机制,比如用户名/密码和令牌/基 ...