本项目Github地址:https://github.com/Rollsom/MyWC.git
项目简介:
实现一个统计目标文件字符数、单词数、行数及其他特殊数据的的命令行程序。并能处理多个文件,同时还能识别一般的通配符。
项目相关要求:
基本功能:(已实现)
-c <文件路径> 统计文件中字符的数量。
-w <文件路径> 统计文件中单词的数量。
-l <文件路径> 统计文件的总行数。
扩展功能:(已实现)
-s -x(相关功能) <搜寻目录路径> <文件名> 批量处理符合条件的文件。(可识别一般通配符:*、?)
-a <文件路径> 统计文件代码行、空白行、注释行的数量。
高级功能:(未实现)
-x 显示图形界面
说明:功能不能叠加使用,-s功能的批量处理也只能使用一种功能。如不能:-c -a <文件路径>
解题思路:
项目要求统计文件的内部信息,很明显就需要使用到文件的输入流。统计文件的各种信息时,逐行读取文件内容,并且根据题目要求写出所需统计的内容符合的正则表达式,将文件每行的内容与正则表达式进行匹配即可。
递归的处理目录及子目录下的所有符合条件的文件,则需要先访问目标目录,逐一判断是否为符合条件的文件或文件夹,是文件则将该文件的路径存放到一个字符串数组,是文件夹则递归访问该文件夹,这样递归访问判断得出所有符合条件的文件。随后遍历字符串数组,逐一对数组中的文件路径进行功能执行。
通配符的处理,则将输入的文件名中的" * "替换为" .*"," ? "替换为" .? ",获得正则表达式作为-s功能中的条件进行文件处理。
判断输入的命令类型,用多个if else语句即可判断。
代码结构:
关键代码说明:
解析命令行参数:
public static void main(String[] args) throws IOException { // TODO Auto-generated method stub /*判断参数的数量是否合法 * 通过Path传入地址 * 判断命令类型,执行不同方法*/ String Path; if(args.length!=2&&args.length!=3&&args.length!=4) System.out.println("参数数量不合法"); if(args[0].equals("-s")) Path = new String(args[2]); else Path = new String(args[1]); if(args[0].equals("-s")) { FindandCarry search = new FindandCarry(Path,args[3]);//传入地址参数 search.GetTargetFilePath(search.Path, search.MenuPath);//寻找目标文件 search.Carry(args[1]);//执行功能 } else { Function F = new Function(Path); if(args[0].equals("-c")) F.CCount(); else if(args[0].equals("-w")) F.WCount(); else if(args[0].equals("-l")) F.LCount(); else if(args[0].equals("-a")) F.ALLCount(); } }
统计行数、字符数、单词数、空白行、注释行、代码行:
public void LCount() throws IOException {//统计行数。 int LineCount = 0; while((s=bin.readLine())!=null) LineCount = LineCount + 1; System.out.println("行数为:"+LineCount); bin.close(); } public void WCount() throws IOException //统计单词数。 { int WordCount = 0; String REX = "\\w+"; Pattern p = Pattern.compile(REX); while((s=bin.readLine())!=null) { Matcher m = p.matcher(s); while(m.find()) WordCount++; } System.out.println("单词数为:"+WordCount); bin.close(); } public void CCount() throws IOException {//统计字符数。 int CharsCount = 0; while((s=bin.readLine())!=null) { char[] s1 = s.toCharArray(); for(char s2 :s1) if(s2 ==' ') continue; else CharsCount=CharsCount+1; } System.out.println("字符数为:"+CharsCount); bin.close(); } public void ALLCount() throws IOException { int CodeLine = 0; int BlankLine = 0; int ExplainLine = 0; while((s=bin.readLine())!=null) { if(s.matches("\\s*\\S?\\s*")) BlankLine++; else if(s.matches("\\s*\\S?\\s*\\/\\/.*")) ExplainLine++; else if(s.matches("\\s*\\S?\\s*\\/\\*.*")) { ExplainLine++; while(s.matches(".*\\*\\/")==false) { s = bin.readLine(); ExplainLine++; } } else CodeLine++ ; } System.out.println("空白行有:"+BlankLine+"行"); System.out.println("代码行有:"+CodeLine+"行"); System.out.println("注释行有:"+ExplainLine+"行"); bin.close(); }
通配符的处理:
//传入Type变量表示要处理的文件的名字格式,将传入的通配符进行改造,变成正则表达式。
px = Type.replaceAll("\\*", ".*"); py = px.replaceAll("\\?", ".?"); this.Type = ".*"+py+".*";
递归找出符合条件的文件,获得它们的路径:
//传入存放符合条件的文件路径Path,及要访问的文件夹路径MenuPath,this.Type表示要处理的文件的名字格式。
public void GetTargetFilePath(ListPath,File MenuPath) { File[] files = MenuPath.listFiles(); if(files == null) return ; for(File f1 : files) { if(f1.isFile()&&f1.getName().matches(this.Type)) Path.add(f1.getPath()); else if(f1.isDirectory()) GetTargetFilePath(Path,f1); } }
运行测试举例:
-a -c -w -l的测试:
-s的批量处理(对我的程序文件):
psp
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
30 | 40 |
· Estimate |
· 估计这个任务需要多少时间 |
30 | 40 |
Development |
开发 |
590 | 960 |
· Analysis |
· 需求分析 (包括学习新技术) |
60 | 90 |
· Design Spec |
· 生成设计文档 |
30 | 30 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
30 | 30 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
20 | 40 |
· Design |
· 具体设计 |
60 | 80 |
· Coding |
· 具体编码 |
240 | 360 |
· Code Review |
· 代码复审 |
120 | 240 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
30 | 90 |
Reporting |
报告 |
90 | 90 |
· Test Report |
· 测试报告 |
60 | 75 |
· Size Measurement |
· 计算工作量 |
10 | 0 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
20 | 15 |
合计 |
710 | 1090 |
总结:
本次的编程内容虽然比较简单,但是实际操作起来发现的问题非常多。虽然基本上都知道要用正则表达式和文件输入流来解决问题,但是具体的操作却不知道,比如正则表达式具体是怎么样的形式,文件输入流的默认路径是哪里,程序不规范等等,这一些问题都消耗了我大量的时间,可以看出我对Java非常的不熟练,在解决问题的过程中,跟同学讨论,我也逐渐开始入门,迅速上手,也比较顺利的完成了基本任务。以后还需经常练习,尽量独立完成。