githup

链接:https://gitee.com/iy2524/WordCount.git

PSP表格

 psp2.1  psp阶段

估计耗时(分钟)

 实际耗时(分钟)
Planning  计划  40  20
 · Estimate  · 估计这个任务需要多少时间  40 20
Development  开发 490  450
 · Analysis  · 需求分析 (包括学习新技术)  30  30
 · Design Spec  · 生成设计文档  60  50
 · Design Review  · 设计复审 (和同事审核设计文档)  60  90
 · Coding Standard  · 代码规范 (为目前的开发制定合适的规范)  10  5
 · Design  · 具体设计  50  55
 · Coding  · 具体编码  130  100
 · Code Review  · 代码复审  60  60
 · Test  · 测试(自我测试,修改代码,提交修改)  90  60
Reporting  报告  60  70
 · Test Report  · 测试报告  40  40
 · Size Measurement  · 计算工作量  10  5

· Postmortem & ProcessImprovement Plan

 · 事后总结, 并提出过程改进计划  10  25
   合计  590 540

以前没有使用过psp表格,本次也是项目完成后才补上的,顺序倒置了。在项目开发中,一天中断断续续地去做项目,具体时间也不好估计,没有想过关注这些,所以也是大概写了下数据。对于本项目自己的估计也不是很准确,更阶段应该做什么事情用多少时间也没经验。不过经过此次项目,以后会学着使用,psp相当于想做计划然后与实际比照,计划时候有助于理清思路,比照时候有助于了解实际开发情况进度,对能力也有一定把握。

解题思路

WordCount功能为统计文件中信息,主要涉及的知识为文件IO流和对字符串的处理。我选择熟悉的java来完成此项目。

一开始看程序预期运行效果和过程,对命令模式启动程序一无所知,百度后发现args中即存储的命令行。

程序测试的时候问题又来了,所需要的args参数该如何加入?百度后又得知在运行配置和调试配置中可以设置,在此,解决了绝大多数问题。

程序实现及代码说明

WordCount功能为统计文件中信息,则按照功能需求依次先完成各种数据的统计,以下是具体功能实现代码

所有对文件的统计方法写在此工具类中

涉及到的知识:对文件IO流的操作,对字符串的操作

以下是此类总览,详细见后面,具体完整代码点最上面码云链接

public class WordCount {
private String input; private String output; private String stop; public static String result="resource/result.txt"; public WordCount(String input,String stop,String output) throws FileNotFoundException
{
this.input=input;
if(output==null)//未指定输出文件 则默认为result
{
this.output=result;
}
else
{
this.output=output;
}
this.stop=stop;
} //返回文件中的字符数
public void CountChars() throws IOException
{
...
} //返回文件中的总行数
public void CountLines() throws IOException
{
...
} //返回文件中的总单词数
public void CountWords() throws IOException
{
...
} //返回 代码行/空行/注释行 的行数
public void CountLinesByKind()throws IOException
{
...
} //使用停用词文件 统计单词个数
public void CountWordsWithLimite() throws IOException
{
...
}
}

java对文件操作的方法有很多,此处主要用了BufferedInputStream和BufferedOutputStream,利用缓冲可以加快效率和速度

所有功能的操作都差不多:(1)读取文件信息(2)处理文件信息(3)将结果写入文件

下面是统计字符个数的完整代码

    public void  CountChars() throws IOException
{
BufferedInputStream input= new BufferedInputStream(
new FileInputStream(this.input));
BufferedOutputStream output=new BufferedOutputStream(
new FileOutputStream(this.output,true));
int count=0;
int x=-1;
char ch;
while((x=input.read())!=-1) //流读取完的标志是返回-1 其他时候返回的为字符的ascii值
{
ch=(char)x;
if(ch!='\r'&&ch!='\n')//换行\n和回车\r不统计为字符
{
count++;
}
}
input.close();
String str=this.input+",字符数:"+count;
output.write(str.getBytes());
output.write("\r\n".getBytes()); //回车 /r和换行/n位置不可换
output.flush();
output.close();
}

下面是其他方法的关键代码

    //返回文件中的总行数
public void CountLines() throws IOException
{
...
int count=0;
int x=-1;
while((x=input.read())!=-1)
{
if((char)x=='\n')//遇到换行符表示一行结束
{
count++;
}
}
count++;
...
}
    //返回文件中的总单词数
public void CountWords() throws IOException
{
...
int count=0;
int x=-1;
boolean InWord=false;//是否读取到某个单词中
char ch='0';
while(true)
{
x=input.read();
ch=(char)x;
if(Character.isLetter(ch)&&InWord==false)//第一次读取到字母 则读取进入到单词中
{
InWord=true;
}
else if(!Character.isLetter(ch)&&InWord==true)//读取到单词中时 读取到第一个非字母的字符 则读完一个单词
{
count++;
InWord=false;
}
if(x==-1)
{
break;
}
}
...
}
    //返回 代码行/空行/注释行 的行数
public void CountLinesByKind()throws IOException
{
...
int all_lines=0;
int blank_lines=0;
int note_lines=0;
int code_lines=0;
String strLine=null;
boolean InNoteLines=false; //bug:若文件末尾有多个回车 则尾不可读 导致总行数少1 未解决
while((strLine=input.readLine())!=null)
{
all_lines++;
strLine.replaceAll("\r", "");//去除换行符和空格 便于后面操作
strLine.replaceAll("\n", "");
strLine=strLine.trim();
strLine.replaceAll(" ", "");
if(InNoteLines==true)
{
note_lines++;
if(strLine.endsWith("*/")||strLine.endsWith("*/}"))
{
InNoteLines=false;
}
}
else if(strLine.startsWith("/*")||strLine.startsWith("{/*")) //进入注释行
{
note_lines++;
if(!strLine.endsWith("*/")&&!strLine.endsWith("*/}"))//本行未注释结束
{
InNoteLines=true;
}
}
else if(strLine.startsWith("//")||strLine.startsWith("{//"))
{
note_lines++;
}
else if(strLine.equals("")||strLine.equals("{")||strLine.equals("}"))
{
blank_lines++;
}
}
code_lines=all_lines-blank_lines-note_lines;
...
}
//使用停用词文件 统计单词个数
public void CountWordsWithLimite() throws IOException
{
...
int count=0;
int x=-1;
char ch;
String stopStr="";
String str="";
List<String> stopList =new ArrayList<>();
boolean InWord=false; //取出停用词装到stopList
while(true)
{
x=stop.read();
if(x==-1)
{
stopList.add(stopStr);
stopStr="";
stop.close();
break;
}
ch=(char)x;
if(ch==' ')
{
stopList.add(stopStr);
stopStr="";
}
else
{
stopStr+=ch;
}
} while(true)
{
x=input.read();
ch=(char)x;
if(Character.isLetter(ch)&&InWord==false)//第一次读取到字母 则读取进入到单词中
{
InWord=true;
str+=ch;
}
else if(!Character.isLetter(ch)&&InWord==true)//读取到单词中时 读取到第一个非字母的字符 则读完一个单词
{
if(!stopList.contains(str))//不在停用词中
{
count++;
}
InWord=false;
str="";
}
else if(InWord==true)//读取字母在单词中
{
str+=ch;
}
if(x==-1)
{
break;
}
}
...
}

主函数及其类中方法如下:

主函数:得到用户的指令(存储在args中的字符串数组)调用analyseCommand()来处理

analyseCommand:首先处理命令是否有效,如参数应该为"-a"格式的字符串加字母形式;如果未文件名,文件是否存在;都满足时则将参数给commandAction执行具体功能。用户输入的信息为字符串数组,我将其放入到了字符串集合的集合中,这里有点绕,目的是便于后面处理指令参数,用户指令如 -c -w input.txt -e stop.txt -o output.txt,则将其分为三个字符串集合-c -w input.txt, -e stop.txt和-o output.txt,每个集合末尾装的是文件名,每个集合中的命令是针对自己文件的。

commandAction:先读取所有文件名,即遍历所有集合,取出集合末尾的字符串,判断其属性分别给到input,output和stop变量中。然后再便利所有指令集合执行相应功能。

public class Main {
public static void main(String[] args) throws FileNotFoundException, IOException
{
analyseCommand(args);
} public static void analyseCommand(String[] args) throws IOException
{
List<List<String>> commandsList =new ArrayList<>();
List<String> commands=new ArrayList<>();
if(args.length==0)//需要用户输出参数
{
System.out.println("Command codes are needed !");
}
else
{
for(int i=0;i<args.length;i++)
{
commands.add(args[i]);
if(!args[i].matches("^-.*"))//不是命令符号
{
if(args[i].contains("."))//是文件名或目录
{
if(!new File(args[i]).exists())//文件不存在
{
System.out.println("The file named "+args[i]+" does not exist");
System.exit(0);
}
else
{
commandsList.add(commands);
commands=new ArrayList<>();
}
}
else//指令有错
{
System.out.println("The "+(i+1)+"th code("+args[i]+") must begin with '-'");
System.exit(0);
}
}
}
}
commandAction(commandsList);
} public static void commandAction(List<List<String>> commandList) throws IOException
{
String input=null,output=null,stop=null; for(List<String> commands:commandList)
{
if(commands.contains("-o"))
{
output=commands.get(commands.size()-1);
}
else if(commands.contains("-e"))
{
stop=commands.get(commands.size()-1);
}
else
{
input=commands.get(commands.size()-1);
}
} WordCount wc=new WordCount(input,stop,output); for(List<String> commands:commandList)
{
for(int i=0;i<commands.size()-1;i++)
{
switch(commands.get(i))
{
case "-c":wc.CountChars();
break;
case "-w":wc.CountWords();
break;
case "-l":wc.CountLines();
break;
case "-s":wc.CountLinesByKind();
break;
case "-e":wc.CountWordsWithLimite();
break;
case "-o":break;
default:System.out.println("No such command code");
}
}
}
}
}

测试

1.初步功能测试

使用此函数的main类文件作为input后测试看预期结果是否相同

程序运行结果如下

结果符合预期,大体功能实现。

2.进一步测试

准备一个标准的类文件(包含足够多的代码,注释等)

使用多种组合命令行

1).未指定输出目录的  默认为bin下的result.txt中

-c -w -l -s C:\Users\iy2524\Desktop\input.txt -e C:\Users\iy2524\Desktop\stop.txt

2).使用其他顺序组合命令

-w -c -s -l  C:\Users\iy2524\Desktop\input.txt

...

3).输入不存在的命令 或者错误的文件名

总结

初步完成了WordCount的基本功,在项目中,遇到了许多问题,都是细节的小问题,问题原因出在对许多方法的细节理解还不到位。通过网上查询相关问题的解答信息,解决了绝大多数问题。项目开发中遇到问题时很常见的,问题有且会时多琐碎复杂的。再遇到问题的时候要耐心分析,要学会使用调试工具,便于分析问题出现过程中的详细信息。借助网络可以解决绝大多数问题,不懂得东西要查,网上大佬多得是,类似的问题解决经验也是有的,所以网络通常是解决问题的第一求助目标,方便有效。在项目代码中,规范使用代码格式和注释等,可以很方便理清代码内容,不至于混乱,在寻找代码分析代码处浪费时间。编写代码不是拿到问题就动手干的,应该先分析问题解决方案,如何最优最有效快速解决问题才是关键,不要写到一半时候才发现问题,到时候会浪费很多时间精力。问题自己独立思考解决固然重要,但是也要考虑其他人的解决思路,如何更好的完成项目,是我们应该学习的地方,总结多人经验,不要固步自封,只顾自己敲自己的代码,毕竟个人能力有限,人多的力量更大。

Java 实现的 简单WordCount功能的更多相关文章

  1. java基础强化——深入理解java注解(附简单ORM功能实现)

    目录 1.什么是注解 2. 注解的结构以及如何在运行时读取注解 2.1 注解的组成 2.2 注解的类层级结构 2.3 如何在运行时获得注解信息 3.几种元注解介绍 3.1 @Retention 3.2 ...

  2. Java 实现《编译原理》简单-语法分析功能-LL(1)文法 - 程序解析

    Java 实现<编译原理>简单-语法分析功能-LL(1)文法 - 程序解析 编译原理学习,语法分析程序设计 (一)要求及功能 已知 LL(1) 文法为: G'[E]: E→TE' E'→+ ...

  3. Java 实现《编译原理》简单词法分析功能 - 程序解析

    Java 实现<编译原理>简单词法分析功能 - 程序解析 简易词法分析功能 要求及功能 (1)读取一个 txt 程序文件(最后的 # 作为结束标志,不可省去) { int a, b; a ...

  4. Java中的简单工厂模式

    举两个例子以快速明白Java中的简单 工厂模式: 女娲抟土造人话说:“天地开辟,未有人民,女娲抟土为人.”女娲需要用土造出一个个的人,但在女娲造出人之前,人的概念只存在于女娲的思想里面.女娲造人,这就 ...

  5. 【JAVA零基础入门系列】Day12 Java类的简单应用

    俗话说的好,实践出真知,所以除了理论知识掌握扎实以外,更重要的是要多加操练,这样才能掌握核心科技. 今天我们就用刚学会的类来实践一下,目标便是完成上一篇中的剁手任务. 我们的商品类已经准备好了,代码重 ...

  6. java Socket实现简单在线聊天(二)

    接<java Socket实现简单在线聊天(一)>,在单客户端连接的基础上,这里第二步需要实现多客户端的连接,也就需要使用到线程.每当有一个新的客户端连接上来,服务端便需要新启动一个线程进 ...

  7. 用Java制作一个简单的图片验证码

    //Java实现简单验证码功能 package project; import java.awt.Color; import java.awt.Font;import java.awt.Graphic ...

  8. Java消息系统简单设计与实现

    前言:由于导师在我的毕设项目里加了消息系统(本来想水水就过的..),没办法...来稍微研究研究吧..简单简单... 需求分析 我的毕设是一个博客系统,类似于简书这样的,所以消息系统也类似,在用户的消息 ...

  9. 利用shell显示wordcount功能

      Shell脚本编程是Linux系统最为核心的技术之一,它能够利用简单的命令来实现一些复杂的功能,同时,由于Linux提供了很多文本处理命令,如grep(grep family), tr, sed, ...

随机推荐

  1. JQuery自动填充控件:autocomplete(自己稍作了修改)

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. prometheus+grafana监控Linux和kubernetes的例子

    1.安装和配置prometheus tar zxvf prometheus-.linux-amd64.tar.gz -C /usr/local/ ln -sv /usr/local/prometheu ...

  3. readline安装

    wget -c ftp://ftp.gnu.org/gnu/readline/readline-6.2.tar.gz tar -zxvf readline-6.2.tar.gz cd readline ...

  4. luoguP2634聪聪可可(点分治)

    题目链接:https://www.luogu.org/problem/P2634 题意:给一颗树,求距离的模3为0的点对数量,注意(1,1)算一个点对,(1,2)和(2,1)算两个点对. 思路:和点分 ...

  5. ARM 版本 瀚高 数据库的启动命令

    1. 在瀚高安装目录下面执行路径 安装目录为: /opt/HighGoDB-4.3.4.3/ bin下./pg_ctl restart -D ../data 本次的密码是: highgo123   2 ...

  6. 详解mysql复制机制--异步复制,半同步复制和并行复制

    图4 那么如何并行化,并行IO线程,还是并行SQL线程?其实两方面都可以并行,但是并行SQL线程的收益更大,因为SQL线程做的事情更多(解析,执行).并行IO线程,可以将从Master拉取和写Rela ...

  7. 洛谷 P2018 消息传递 题解

    题面 总体来说是一道从下往上的DP+贪心: 设f[i]表示将消息传给i,i的子树全部接收到所能消耗的最小时间: 那么对于i的所有亲儿子节点j,我们会贪心地先给f[j]大的人传递,然后次大..... 可 ...

  8. T100 事务的开始与结束

    例如: IF cl_ask_confirm('apm-00801') THEN CALL s_transaction_begin() IF NOT axmt500_change_xmdc015('u' ...

  9. Gluster的搭建和使用

    Gluster的搭建和使用 序言 我们为什么要去使用分布式存储,在一家大型公司或者大规模的集群中,大家可能会经常遇到一个问题,我的数据怎么存放,放在那,数据空间不够了怎么办,这些问题经常困扰着我们. ...

  10. MySQL解惑——GROUP BY隐式排序

    原文:MySQL解惑--GROUP BY隐式排序 MySQL中GROUP BY隐式排序是什么概念呢? 主要是其它RDBMS没有这样的概念,如果没有认真了解过概念,对这个概念会感觉有点困惑,我们先来看看 ...