本项目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(List<String> Path,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非常的不熟练,在解决问题的过程中,跟同学讨论,我也逐渐开始入门,迅速上手,也比较顺利的完成了基本任务。以后还需经常练习,尽量独立完成。