wc.exe实现(java)
项目的Github地址:https://github.com/hrzgj/-
一、项目简介
wc.exe 是一个常见的工具,它能统计文本文件的字符数、单词数和行数。这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数、单词数和行数。
实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。
具体功能要求:
程序处理用户需求的模式为:
wc.exe [parameter] [file_name]
基本功能列表:
wc.exe -c file.c //返回文件 file.c 的字符数
wc.exe -w file.c //返回文件 file.c 的词的数目
wc.exe -l file.c //返回文件 file.c 的行数
扩展功能:
-s 递归处理目录下符合条件的文件。
-a 返回更复杂的数据(代码行 / 空行 / 注释行)。
空行:本行全部是空格或格式控制字符,如果包括代码,则只有不超过一个可显示的字符,例如“{”。
代码行:本行包括多于一个字符的代码。
注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释:
} //注释
在这种情况下,这一行属于注释行。
二、PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
20 |
20 |
· Estimate |
· 估计这个任务需要多少时间 |
300 |
420 |
Development |
开发 |
170 |
240 |
· Analysis |
· 需求分析 (包括学习新技术) |
30 |
30 |
· Design Spec |
· 生成设计文档 |
10 |
10 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
10 |
10 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
10 |
10 |
· Design |
· 具体设计 |
30 |
60 |
· Coding |
· 具体编码 |
40 |
40 |
· Code Review |
· 代码复审 |
30 |
30 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
60 |
120 |
Reporting |
报告 |
30 |
30 |
· Test Report |
· 测试报告 |
10 |
10 |
· Size Measurement |
· 计算工作量 |
10 |
10 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
10 |
10 |
合计 |
|
470 |
630
|
三、解题思路
因为要读取文件的内容,而java封装了很好的io,故使用java来进行编程。需要统计单词,首先想到可以用正则表达式去分割单词,处理一个目录下的文件,可以用递归处理。
四、设计实现过程
根据每个需求来创建一个方法来实现每一个具体的功能,因为有有5个需求,故构建5个方法,分别来实现-w,-c,-l,-s,-a的功能。用主函数调用各个方法。
五、代码说明
首先是主函数获取参数并判断参数是否正确,文件是否存在,再根据输入的参数进行对应的操作
//统计文件行数 public static void countLine (String fileName,String absolutePath) throws Exception { BufferedReader br=new BufferedReader(new FileReader(new File(absolutePath))); String line =null; int sum = 0; while((line=br.readLine())!=null) { sum++; } System.out.println((fileName==null?"":fileName)+"文件行数为:"+sum); } //统计字符数 public static void countChar(String fileName,String path) throws Exception { BufferedReader br=new BufferedReader(new FileReader(new File(path))); int sum = 0 ; String line; while ((line = br.readLine()) != null){ sum+=line.length(); } System.out.println((fileName==null?"":fileName)+"文件字符数为:"+sum); } //统计单词数 public static void countWord(String fileName,String path) throws Exception { BufferedReader br=new BufferedReader(new FileReader(new File(path))); //使用正则进行分割:空格 Tab { } ;: ~ ! ? ^ % + - * / | & >> >>> << <<< [ ] ( ) \\ int countWord = 0; String str = ""; while((str = br.readLine()) != null){ //这里只使用部分符号,还有更多符号没有进行添加 countWord += str.split("\\s+|\\(|\\)|,|\\.|\\:|\\{|\\}|\\-|\\*|\\+|;|\\?|\\/|\\\\|/").length; } System.out.println((fileName==null?"":fileName)+"文件单词数为:"+countWord); } //递归处理目录的子文件 public static void countDir(String filePath) throws Exception { File dir = new File(filePath); if (!dir.isDirectory() || !dir.exists()){ System.out.println("你指定的不是目录"); return; } File[] files = dir.listFiles(); assert files != null; for (File file : files) { if (file.isDirectory()){ countDir(file.getAbsolutePath()); }else { String name = file.getName(); String absolutePath = file.getAbsolutePath(); //调用其他三个方法 countLine(name,absolutePath); countChar(name,absolutePath); countWord(name,absolutePath); } } } /** * 统计空行,代码行,注释行 */ public static void countFileSpecialLine(String filePath) throws IOException { //空行 int spaceNum = 0; //注释行 int noteNum = 0; //代码行 int codeNum = 0; BufferedReader br=new BufferedReader(new FileReader(new File(filePath))); String line; while ( (line = br.readLine()) != null){ String s = line.replaceAll("[\\s;]", ""); //空行 if (s.length() == 0){ spaceNum++; }else if (s.length() == 1 && ("{".equals(s) || "}".equals(s)) ){ spaceNum++; } //注释行 else if ( (s.startsWith("{") || s.startsWith("}") ) && s.contains("//")){ noteNum++; }else if (s.startsWith("//")){ noteNum++; }else if (s.startsWith("/*") && s.length()>=4 && s.endsWith("*/")){ noteNum++; }else if (s.startsWith("/*")){ noteNum++; while (true){ if ((line = br.readLine()) != null){ noteNum++; if (line.endsWith("*/")) { break; } }else { break; } } }else //代码行 { codeNum++; } } System.out.println("文件空行数为:"+spaceNum); System.out.println("文件注释行数为:"+noteNum); System.out.println("文件代码行数为:"+codeNum); }
六、测试
空文件:
一个字符文件:
一个词文件:
一行的文件:
源文件:
七,项目小结
预估的时间跟我开发时间相差有点多,在项目开发的时候会出现一些难以预料的bug,做测试的时候花了不少时间。同时对正则表达式的使用不够熟练,需要查阅不少资料才能实现我想要的目的。总的来说,还需不断努力继续学习