github项目地址 https://github.com/bpgg/WordCount
预测PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
60 | |
· Estimate |
· 估计这个任务需要多少时间 |
30 | |
Development |
开发 |
600 | |
· Analysis |
· 需求分析 (包括学习新技术) |
100 | |
· Design Spec |
· 生成设计文档 |
60 | |
· Design Review |
· 设计复审 (和同事审核设计文档) |
60 | |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
30 | |
· Design |
· 具体设计 |
200 | |
· Coding |
· 具体编码 |
200 | |
· Code Review |
· 代码复审 |
100 | |
· Test |
· 测试(自我测试,修改代码,提交修改) |
30 | |
Reporting |
报告 |
100 | |
· Test Report |
· 测试报告 |
30 | |
· Size Measurement |
· 计算工作量 |
30 | |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
100 | |
合计 |
项目要求及解题思路
实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。
基本功能
wc.exe -c file.c //返回文件 file.c 的字符数
- 具体思路:使用io流读取目标文件的每一行,并累计每一行字符串的长度。
wc.exe -w file.c //返回文件 file.c 的词的数目
- 具体思路:使用正则表达式确定所读取的每行字符串中所匹配到的单词数,进行累加。
wc.exe -l file.c //返回文件 file.c 的行数
- 具体思路:直接累计读取的行数。
拓展功能
-s 递归处理目录下符合条件的文件。
- 具体思路:
- 文件格式有要求,所以先写了一个文件名过滤器
- 判断传入参数是否为需求文件或者目录
- 递归查找,若为目标文件,输出文件名。若为目录,则递归查找。
-a 返回更复杂的数据(代码行 / 空行 / 注释行)。
- 对需求的定义:
-
空行:整行为空白字符,或者空白字符加[{;}]
-
注释行:
单行注释:[{;}]?//开头的视为注释行
块注释:[{;}]?/开头,/(//s)+结尾的视为快注释中的行。 3. 代码行:文本总行数去掉空行和注释行。
-
高级功能:
-x 参数。这个参数单独使用。如果命令行有这个参数,则程序会显示图形界面,用户可以通过界面选取单个文件,程序就会显示文件的字符数、行数等全部统计信息。
遇到的困难及解决方法
困难描述
在匹配注释行数中,对正则表达式不过熟悉,并且对于注释行可能出现的类型没有全面认识。
做过哪些尝试
放弃使用正则表达式,转而使用条件判断语句判断每一行数据。<br>
单行注释比较简单。<br>
多行注释要注意判断每行读取到是否含有/*,并且做标记,直到读到*/。<br>
是否解决
是的。不过最后还是使用正则表达式,因为代码比较简洁。
有何收获
熟悉了正则表达式的某些应用
设计实现过程
说明:使用两个类处理程序,一个Worker类用于实现特定需求,一个是Main类用于根据所输入参数调用相应方法实现需求。
代码说明
- 单词数:
单词定义:只包含连续的英文字母,在这里没有考虑单词跨行的情况
1 String REGEX ="\\b[a-zA-Z]+\\b"; 2 String currentLine; 3 Pattern p = Pattern.compile(REGEX); 4 Matcher m; 5 while((currentLine=reader.readLine())!=null) { 6 currentLine=currentLine.trim(); 7 m= p.matcher(currentLine); 8 while(m.find()) { 9 count++; 10 } 11 }
- 字符数:
字符定义:包括空白字符
1 while((currentLine=reader.readLine())!=null) { 2 count+=currentLine.length(); 3 }
- 注释行数
注释行的定义上文已提及,在这里不再赘述。
1 /* 2 注释说明: 3 单行注释:[{;}]?//开头的视为注释行 4 块注释:[{;}]?/*开头,*/(//s)+结尾的视为快注释中的行。 5 由此写出对应的正则表达式进行匹配。 6 */ 7 String Single_Line_Note_REGEX="(\\s*)([{};]?)(\\s*)(//)(.*)"; 8 String Block_Note_Start_REGEX="(\\s*)([{};]?)(\\s*)(/{1})(\\*{1})(.*)"; 9 String Block_Note_End_REGEX="(.*)(\\*{1})(/{1})(\\s*)"; 10 while((currentLine=reader.readLine())!=null) { 11 if(currentLine.matches(Single_Line_Note_REGEX)) { 12 count++; 13 }else if(currentLine.matches(Block_Note_Start_REGEX)) { 14 count++; 15 while((currentLine=reader.readLine())!=null) { 16 if(currentLine.matches(Block_Note_End_REGEX)) { 17 count++; 18 break; 19 }else { 20 count++; 21 } 22 } 23 } 24 }
- 查询指定文件
根据输入参数指定文件和过滤类型
1 /* 2 思路分析:递归判断输入参数是否为目录,若是递归查询,若为目标文件,则输出文件名。 3 4 */ 5 public class myFileFilter implements FileFilter { 6 @Override 7 public boolean accept(File file) { 8 9 if(file.isDirectory()) 10 return true; 11 else{ 12 String name = file.getName(); 13 if(name.endsWith(getFile_type())){ 14 return true; 15 } 16 else { 17 return false; 18 } 19 } 20 21 } 22 23 } 24 public void getAllFilePath(String rootPath) { 25 26 File file = new File(rootPath); 27 File[] files = file.listFiles(new myFileFilter()); 28 for(int i=0;i<files.length;i++){ 29 if(files[i].isDirectory()){ 30 getAllFilePath(files[i].getPath()); 31 } 32 else{ 33 System.out.println(files[i].getPath()); 34 } 35 } 36 }
测试运行
基本功能的测试
高级功能测试
获取特殊行数
获取指定文件名
实际PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
60 | 30 |
· Estimate |
· 估计这个任务需要多少时间 |
30 | 30 |
Development |
开发 |
600 | 600 |
· Analysis |
· 需求分析 (包括学习新技术) |
100 | 100 |
· Design Spec |
· 生成设计文档 |
60 | 60 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
60 | 60 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
30 | |
· Design |
· 具体设计 |
200 | 200 |
· Coding |
· 具体编码 |
200 | 180 |
· Code Review |
· 代码复审 |
100 | 60 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
30 | 30 |
Reporting |
报告0 |
100 | 160 |
· Test Report |
· 测试报告 |
30 | 30 |
· Size Measurement |
· 计算工作量 |
30 | 30 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
100 | 80 |
合计 |
760 | 790 |
项目小结
不足之处
- 代码不够简洁,数据没有封装好:在观察了其他同学提交的作业,我深深感到自己编写的代码规范性不好,没有对所有代码的封装保持一致的风格。数据封装这方面没有把相关常量定义在一个接口文件中。
学习收获
- 正则表达式:对正则表达式重新了解并做了笔记
- javaAPI中的一些方法:文件名过滤器,分割字符串,去除字符串空白字符。