GitHub地址:https://github.com/hanfeng98/WC
项目简介:
实现一个统计目标文件字符数、单词数、行数及其他特殊数据的的命令行程序。并能处理多个文件,同时还能识别一般的通配符。
基本项目要求:
基本功能:(已实现)
-c <文件路径> 统计文件中字符的数量。
-w <文件路径> 统计文件中单词的数量。
-l <文件路径> 统计文件的总行数。
扩展功能:(已实现)
-s <搜寻目录路径> <文件类型名> 批量处理符合条件的文件。(可识别一般通配符:*、?)
-a <文件路径> 统计文件代码行、空白行、注释行的数量。
高级功能:(未实现)
-x 显示图形界面
解题思路
项目开始后,先考虑了载入文本的方法,一是把代码内容全部通过输入输出流导入到一个长字符串中,二是通过输入输出流的readline方法进行边输入边统计,并且把统计功能封装成方法,通过调用方法进行统计,方法中通过使用正则表达式来区分目标对象。命令行输入通过map建立映射结合switch调用功能。
代码结构:
关键代码说明:
解析命令行参数
1 public class WC { 2 public static void main(String[] args) { 3 // TODO 自动生成的方法存根 4 System.out.print("请输入需要进行的操作与操作对象:"); 5 Scanner sc=new Scanner(System.in); 6 String temp[]=sc.nextLine().split("\\s+"); 7 String option=temp[0]; 8 String filepath=temp[1]; 9 String filetype=temp[2].substring(temp[2].lastIndexOf(".")+1); 10 String tongpei=temp[2].substring(0, temp[2].indexOf(".")); 11 File file=new File(filepath); 12 13 14 try { 15 sc.close(); 16 }catch (Exception e){ 17 e.printStackTrace(); 18 }; 19 20 21 Map<String,Integer> map=new HashMap<String,Integer>();//通过map建立映射关系与switch调用方法 22 map.put("-c",1); 23 map.put("-w",2); 24 map.put("-l",3); 25 map.put("-s",4); 26 map.put("-a",5); 27 28 29 wordcount count=new wordcount(); 30 31 switch (map.get(option)) { 32 case 1:count.charactercount(file);break; 33 case 2:count.wordcount(file);break; 34 case 3:count.linecount(file);break; 35 case 4:count.rtcatalog(file,tongpei,filetype);break; 36 case 5:count.CountSpecialLines(file);break; 37 default:System.out.println("请重新按格式输入"+"\n"+"[parameter] [file_name]"); 38 } 39 } 40 41 } 42 43
统计行数、字符数、单词数
1 void charactercount(File file) { 2 String str=null; 3 char temp[]=null; 4 int characternum=0; 5 try { 6 InputStreamReader ir =new InputStreamReader(new FileInputStream(file)); 7 BufferedReader BF=new BufferedReader(ir); 8 while((str=BF.readLine())!=null) { 9 temp=str.toCharArray(); 10 characternum+=temp.length; 11 } 12 ir.close(); 13 BF.close(); 14 System.out.println("字符数:"+characternum); 15 } catch (FileNotFoundException e) { 16 // TODO 自动生成的 catch 块 17 System.out.println("无法找到指定的文件"); 18 e.printStackTrace(); 19 }catch(Exception e) { 20 e.printStackTrace(); 21 System.out.println("文件读取失败"); 22 } 23 24 } 25 26 void wordcount(File file) { 27 String str=null; 28 int wordnum=0; 29 try { 30 InputStreamReader ir =new InputStreamReader(new FileInputStream(file)); 31 BufferedReader BF=new BufferedReader(ir); 32 while((str=BF.readLine())!=null) { 33 wordnum+=str.split("\\W").length; 34 } 35 ir.close(); 36 BF.close(); 37 System.out.println("单词数:"+wordnum); 38 } catch (FileNotFoundException e) { 39 // TODO 自动生成的 catch 块 40 System.out.println("无法找到指定的文件"); 41 e.printStackTrace(); 42 }catch(Exception e) { 43 e.printStackTrace(); 44 System.out.println("文件读取失败"); 45 } 46 } 47 48 49 void linecount(File file) { 50 int linenum=0; 51 try { 52 InputStreamReader ir =new InputStreamReader(new FileInputStream(file)); 53 BufferedReader BF=new BufferedReader(ir); 54 while(BF.readLine()!=null) { 55 linenum++; 56 } 57 ir.close(); 58 BF.close(); 59 System.out.println("总行数:"+linenum); 60 } catch (FileNotFoundException e) { 61 // TODO 自动生成的 catch 块 62 System.out.println("无法找到指定的文件"); 63 e.printStackTrace(); 64 }catch(Exception e) { 65 e.printStackTrace(); 66 System.out.println("文件读取失败"); 67 } 68 } 69
1 void CountSpecialLines(File file) { 2 int blanklines=0; 3 int commentlines=0; 4 int codelines=0; 5 String temp=null; 6 String blanklinesregex ="\\s*\\W?\\s*"; 7 String bclbeginregex="\\s*.?\\s*/\\*.*"; 8 String bclendregex="\\s*.?\\s*\\*/.*"; 9 String clregex="\\W?//.*"; 10 boolean blcflag=false; 11 try { 12 /* 13 *首先判断是否空行,同时块注释标记是否false, 14 *其次判断是否进入块注释,若进入将块注释标记true 15 *若下一行块注释标记为true,注释行自增 16 *若下一行匹配到块注释结尾且块注释标记为true,注释行自增同时块注释标记改为false 17 *上述情况皆不成立代码行自增 18 19 */ 20 InputStreamReader ir =new InputStreamReader(new FileInputStream(file)); 21 BufferedReader BF=new BufferedReader(ir); 22 while((temp=BF.readLine())!=null) { 23 if(temp.matches(blanklinesregex)&&(blcflag==false)) { 24 blanklines++; 25 }else if(temp.matches(bclbeginregex)&&temp.matches(bclendregex)) { 26 commentlines++; 27 blcflag=false; 28 }else if(temp.matches(clregex)) { 29 commentlines++; 30 }else if(temp.matches(bclbeginregex)||blcflag==true) { 31 commentlines++; 32 blcflag=true; 33 }else if((temp.matches(bclendregex))&&(blcflag==true)) { 34 commentlines++; 35 blcflag=false; 36 }else if(blcflag==false){ 37 codelines++; 38 } 39 } 40 ir.close(); 41 BF.close(); 42 } catch (FileNotFoundException e) { 43 // TODO 自动生成的 catch 块 44 System.out.println("无法找到指定的文件"); 45 e.printStackTrace(); 46 }catch(Exception e) { 47 e.printStackTrace(); 48 System.out.println("文件读取失败"); 49 } 50 System.out.println(" 空行 :"+blanklines); 51 System.out.println("代码行:"+codelines); 52 System.out.println("注释行:"+commentlines); 53 }
1 void rtcatalog(File filepath,String filename,String str) { 2 File listfile[]=filepath.listFiles(); 3 String tongpei=null; 4 if(filename==null) { 5 tongpei=".*"; 6 }else if(filename.contains("*")) {//通过pattern模式筛选出指定文件 7 tongpei=filename.replaceAll("\\*",".*"); 8 }else if(filename.contains("?")) { 9 tongpei=filename.replaceAll("\\?",".?"); 10 } 11 Pattern p=Pattern.compile(tongpei);
通过通配符模式筛选指定文件
1 for(File file:listfile) { 2 if(file.isDirectory()) { 3 rtcatalog(file,filename,str); 4 }else if(file.exists()){ 5 Matcher m=p.matcher(file.getName()); 6 if(file.getName().endsWith(str)&&m.find()) { 7 System.out.println("文件所在目录:"+file.getAbsolutePath()); 8 charactercount(file); 9 wordcount(file); 10 linecount(file); 11 CountSpecialLines(file); 12 } 13 }else if(!file.exists()) { 14 System.out.println("无法找到指定的路径目录下指定类型的文件"); 15 } 16 } 17 }
只有一行的文件
典型的源文件
递归遍历指定目录指定类型的文件
通配符 通过通配符筛选走文件
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 30 | 40 |
· Estimate | · 估计这个任务需要多少时间 | 15 | 20 |
Development | 开发 | 300 | 360 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 90 |
· Design Spec | · 生成设计文档 | 30 | 40 |
· Design Review | · 设计复审 (和同事审核设计文档) | 20 | 20 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 15 | 20 |
· Design | · 具体设计 | 60 | 80 |
· Coding | · 具体编码 | 300 | 300 |
· Code Review | · 代码复审 | 120 | 180 |
· Test | · 测试(自我测试,修改代码,提交修改) | 90 | 90 |
Reporting | 报告 | 90 | 120 |
· Test Report | · 测试报告 | 60 | 45 |
· Size Measurement | · 计算工作量 | 10 | 5 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 15 |
合计 | 1220 | 1425 |
总结:
本以为此项目会比较简单,但实际进行起来发现设计阶段的设计不足,查阅资料后知道要用正则表达式和文件输入流来解决问题,但是具体操作是发现正则表达式的表达式有些许疑问,特别是对于特定文件的筛选时,控制符号与正则表达式的转换让我耗费了不少时间,这让我深感基础的薄弱。