项目地址:https://gitee.com/yangfj/wordcount_project
1.软件需求分析:
撰写PSP表格:
PSP2.1 |
PSP阶段 |
预估耗时 (分钟) |
实际耗时 (分钟) |
Planning |
计划 |
20 |
15 |
· Estimate |
· 估计这个任务需要多少时间 |
20 |
15 |
Development |
开发 |
960 |
880 |
· Analysis |
· 需求分析 (包括学习新技术) |
10 |
20 |
· Design Spec |
· 生成设计文档 |
40 |
20 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
10 |
30 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
50 |
10 |
· Design |
· 具体设计 |
50 |
20 |
· Coding |
· 具体编码 |
500 |
650 |
· Code Review |
· 代码复审 |
100 |
30 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
200 |
50 |
Reporting |
报告 |
150 |
100 |
· Test Report |
· 测试报告 |
80 |
50 |
· Size Measurement |
· 计算工作量 |
20 |
20 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
50 |
30 |
|
合计 |
1130 |
995 |
结果分析,在完成编码撰写博客的时候,确实发现了许多计划与实际出入的地方,比如说代码规范,在实际编码的时候,根本没有考虑到这一点,只是在最终编写完成之后才意识到,于是最后才开始改编码规范,写次开发的时候就应该提前考虑,虽然只是一个人在开发。还有就是总体来说并不是很完整的进行了测试,只是有一些单元测试,以后会多了解一下代码测试这一块的技能。
2.解题思路
因为以前用到的代码管理工具都是SVN,还没有用过Git ,只是偶尔在GitHub上面逛逛,所以首先想的是成功安装Git,并且实现代码管理,然后就找了好久的资料,包括Git如何提交到码云等等,详见我的另一篇博文:
https://www.cnblogs.com/shoneworn/p/8251556.html
然后看了看题目,发现应该先确定用什么语言代码来实现,虽然自己擅长C#,也学过Python,但还是决定用java语言比较好,一个是因为自己现在正在学习java,正好可以通过这个项目提升自己,主要采用的技术是java IO流方面的技术。
1.对于常见的java项目,应该利用什么才能实现在命令行中进行输入输出的信息读取?
2.如何判断控制台是要求的统计字符数,单词数,总行数,存入特定文件的相应基础功能?
3.如何在支持基础功能的基础上,拓展其待实现的功能而又能与原代码区分开来?
3.需求分析
具体的需求其实大致可以总结为一下几点:
1.输入:
输入指定的文件,采用程序统计文件的字符数、单词数、行数、
2.输出:
输出文件(以指定的格式)
3.拓展:
支持 返回高级选项(代码行 空行 注释行)
递归处理符合条件的文件,考虑程序的时间复杂度和空间复杂度
4.程序实现过程
项目一共两个文件,一个为主函数,一个为实现具体功能类。
mian函数:
public class WorkCount { public static void main(String[] args) throws Exception { // 统计一个文件的字符数,单词数,行数 Scanner input = new Scanner(System.in); System.out.println("please input path:"); String path = input.next(); int countChar = 0; int countword = 0; int countline = 0; InputStreamReader isr = new InputStreamReader(new FileInputStream(path)); //InputStreamReader将字符流向字节流转换。 //InputStreamReader isr = new InputStreamReader(new FileInputStream(绝对文件名)); //用来读取文件中的数据 BufferedReader br = new BufferedReader(isr);//使用缓冲区,可以使用缓冲区的read(),readLine()方法; while(br.read()!=-1)//read()=-1代表数据读取完毕 { String s = br.readLine(); countChar += s.length();//字符个数就是字符长度 countword += s.split(" ").length;//split() 方法用于把一个字符串分割成字符串数组,字符串数组的长度,就是单词个数 countline++;//因为是按行读取,所以每次增加一即可计算出行的数目 } isr.close();//关闭文件 System.out.println("char cont "+countChar); System.out.println("word count "+countword ); System.out.println("line count "+countline); } }
实现具体功能类:
返回字符的个数
int CharCount(String s)//用来输入文件并返回字符的个数 { int count = 0; Pattern p = Pattern.compile("[a-zA-Z]"); Matcher m = p.matcher(str); while(m.find()){ count++; } return count; }
}
返回单词出现总数 :
public static int countdanci(String[] args) { //逐行读文件 BufferedReaderbr = null; try { Map<String,Integer>map = newHashMap<String,Integer>(); br = new BufferedReader(new FileReader("d:/mywords.txt")); Stringline; while(null != (line = br.readLine())){ System.out.println(line); //将字符串用空格分隔 String[]ss = line.split("\s+"); for(String s : ss){ if(map.containsKey(s)){ map.put(s, map.get(s)+1); }else{ map.put(s, 1); } } } Set<String>keys = map.keySet(); for(String key : keys){ System.out.println(key + "有:" + map.get(key) + "个."); } }catch(FileNotFoundException e) { e.printStackTrace(); }catch(IOException e) { e.printStackTrace(); }finally { if(null != br){ try { br.close(); }catch(IOException e) { e.printStackTrace(); } } }
文件总行数:
public static HangCount(String[] args) { try{ File file =new File("c:\test.txt"); if(file.exists()){ FileReader fr = new FileReader(file); LineNumberReader lnr = new LineNumberReader(fr); int linenumber = 0; while (lnr.readLine() != null){ linenumber++; } System.out.println("Total number of lines : " + linenumber); lnr.close(); }else{ System.out.println("File does not exists!"); } }catch(IOException e){ e.printStackTrace(); } }
文件空白行数,注释行数
public static void CountLine(File f) throws FileNotFoundException, IOException{ //通过调用一个之前定义的对象来表示此文件连接,file参数表示的路径作为参数调用javaLine方法 String strLine = "";//创建了一个对象。并且加入字符串池中 String str = fromFile(f); //str为引用 "" 是 引用指向的的值,定义一个String 类型的变量str,并为其赋值 if (str.length() > 0) { while (str.indexOf(' ') != -1) { //通过一个wile循环体判断这个值,从而做到字符串处理,使得字符串以正确方式显示 totle++; strLine = str.substring(0, str.indexOf(' ')).trim(); if (strLine.length() == 0 ) { blank++; }else if (strLine.charAt(0) == '*' || strLine.charAt(0) == '/') { comments++; }else{ source++; String regEx = "^*//"; if(regEx(strLine,regEx)){ comments++; } } str = str.substring(str.indexOf(' ') + 1, str.length()); //返回给定区间的字符串,以上经过转换后,str能够正常显示 } } }
输出到文件:
public void outPutfile(String infilename,String outfiename) { try { fileReader(infilename); File file=new File(outfiename); if(!file.exists()) { file.createNewFile(); } String lineSents=""; String wordSents=" "; String charSents=" "; String charCon=CharCount/callCounter+""; String lineCon=LineCount/callCounter+""; String wordCon=WordCount/callCounter+""; charSents=charSents.concat(charCon).concat(" ");//使用concat()方法链接两个字符串 lineSents=lineSents.concat(lineCon).concat(" "); wordSents=wordSents.concat(wordCon).concat(" "); FileWriter fw=new FileWriter(file.getAbsoluteFile()); BufferedWriter bWriter=new BufferedWriter(fw); bWriter.write(charSents);//写入到文件 bWriter.write(lineSents); bWriter.write(wordSents); bWriter.close();//必须关闭才能写入文件,否则写入无效 fw.close(); if(file.length()!=0) System.out.println("write file succeed..."); else System.out.println("write file failed..."); } catch (IOException e) {//跑出异常 // TODO Auto-generated catch block e.printStackTrace(); } }
5.测试过程:
wc.exe -c file.c //返回文件 file.c 的字符数
wc.exe -w file.c //返回文件 file.c 的单词总数
wc.exe -l file.c //返回文件 file.c 的总行数
wc.exe -o outputFile.txt //将结果输出到指定文件outputFile.txt
......
6.测试结果:
wc.exe -c C:LearningJavacode empsrccomhcedudaoLoginDao.java
wc.exe -w C:LearningJavacode empsrccomhcedudaoLoginDao.java
wc.exe -l C:LearningJavacode empsrccomhcedudaoLoginDao.java
wc.exe -c C:LearningJavacode empsrccomhcedudaoLoginDao.java
wc.exe -m C:LearningJavacode empsrccomhcedudaoLoginDao.java
7.总结
这次的WorkCount作业,其实是一个较为完整的项目,其中包括了需求分析、系统设计、编码实现、测试分析等等。以前写代码并没有写过如此完整的代码流程,其中很多时候都没有写过文档和测试分析,通过这次的编码,我意识到了代码的安全性,程序的健壮性。规范的代码更对之后的测试分析有利。同时更要考虑到用户的感受,让代码变的更加人性化才行。
最后,其实这次的代码我还存在着许多的不足,我最开始拿到这个项目,写完需求分析之后就没有动过博客,后面逐一实现代码之后又对博客进行的删减去,总的来说,还是一直都在写代码,而忽视了文档的重要性,在以后的编码过程中,更应该加强对文档的投入。
8.参考文献
邹欣老师在《构建之法》中设计的第一项个人作业:http://www.cnblogs.com/xinz/p/7426280.html