Github项目地址:https://github.com/siberia0015/PersonProject-Jav
PSP表格:
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 20 |
• Estimate | • 估计这个任务需要多少时间 | 600 | 630 |
Development | 开发 | 530 | 695 |
• Analysis | • 需求分析 (包括学习新技术) | 60 | 60 |
• Design Spec | • 生成设计文档 | 10 | 5 |
• Design Review | • 设计复审 | 10 | 20 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 60 | 140 |
• Design | • 具体设计 | 120 | 150 |
• Coding | • 具体编码 | 180 | 180 |
• Code Review | • 代码复审 | 30 | 40 |
• Test | • 测试(自我测试,修改代码,提交修改) | 60 | 100 |
Reporting | 报告 | 40 | 50 |
• Test Repor | • 测试报告 | 15 | 15 |
• Size Measurement | • 计算工作量 | 10 | 20 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 15 | 15 |
合计 | 600 | 765 |
计算模块接口的设计与实现过程:
首先,题目要求程序能够接收一个文件,文件名由控制台输入,因此需要一个方法能够接收控制台输入的值作为文件的地址参数。因为题目还需要求把不同功能的模块封装成独立的模块,因此我把接收文件的代码段直接放在各个方法里。然后,题目要求代码至少要对数据进行四种统计,统计字符出现次数、单词(符合要求的)出现次数、有效行数以及出现频率最高的十个单词。我使用BufferedReader来依次读取文件的每一行,对于行数统计,我在读取的同时会记下长度不为0的行的个数;对于字符统计,我用一个StringBuffer记下每行的内容,然后把它转为String,由于此方法无法记下换行符,所以我最后用这个String的长度加上总行数(包括空白行)-1作为字符数;对于单词(有效)统计,我前面的方法同上,之后用split()方法将String分成一个String数组,通过一系列方法筛选出符合条件的元素,统计个数;对于词频统计,我用一个HashMap存放获得的符合条件的单词及其出现次数,然后对其进行排序并返回。最后,用一个输出函数接收之前方法返回的参数并新建一个新的result.txt输出。
WordCount.java:
1 import java.util.HashMap; 2 import java.util.Map; 3 4 /*import static com.siberia.demo.lib.*;*/ 5 6 7 public class WordCount { 8 public static void main(String[] args) { 9 String pathname = args[0]; 10 int characters = 0; 11 int words = 0; 12 int lines = 0; 13 Map<String, String> map = new HashMap<String, String>(); 14 /*查询&统计*/ 15 characters = lib.countChar(pathname); 16 words = lib.countWord(pathname); 17 lines = lib.countLines(pathname); 18 map = lib.countFrequency(pathname); 19 /*输出结果*/ 20 lib.printFile(characters, words, lines, map); 21 System.out.println("completed"); 22 } 23 }
lib.java:
1 /* 2 import com.siberia.demo.MapValueComparator; 3 */ 4 5 import java.io.*; 6 import java.util.*; 7 8 9 public class lib { 10 /*统计字符数*/ 11 public static int countChar(String filePath){ 12 int characters=0; 13 try { 14 String encoding = "UTF-8"; 15 File file = new File(filePath); 16 if (file.isFile() && file.exists()) { 17 InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding); 18 int totalLine=0; 19 /*读取文件数据*/ 20 StringBuffer sb=null; 21 BufferedReader br1; 22 try{ 23 br1=new BufferedReader(new FileReader(file)); 24 String temp=br1.readLine(); 25 sb=new StringBuffer(); 26 while(temp!=null){ 27 sb.append(temp); 28 /*统计总行数*/ 29 totalLine++; 30 temp=br1.readLine(); 31 } 32 } 33 catch (Exception e){ 34 e.printStackTrace(); 35 } 36 /*读取的内容*/ 37 String info=sb.toString(); 38 /*统计字符个数*/ 39 characters=info.length()+totalLine-1; 40 read.close(); 41 } else { 42 System.out.println("找不到指定的文件"); 43 } 44 } catch (Exception e) { 45 System.out.println("读取文件内容出错"); 46 e.printStackTrace(); 47 } 48 return characters; 49 } 50 /*统计单词数*/ 51 public static int countWord(String pathname) { 52 StringBuilder content = new StringBuilder(""); 53 int words = 0; 54 try { 55 String encoding = "UTF-8"; 56 File file = new File(pathname); 57 if (file.isFile() && file.exists()) { 58 InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding); 59 /*读取文件数据*/ 60 StringBuffer sb = null; 61 BufferedReader br1; 62 try { 63 br1 = new BufferedReader(new FileReader(file)); 64 String temp = br1.readLine(); 65 sb = new StringBuffer(); 66 while (temp != null) { 67 sb.append(temp); 68 temp = br1.readLine(); 69 70 } 71 } catch (Exception e) { 72 e.printStackTrace(); 73 } 74 String info = sb.toString(); 75 String s[] = info.split(",|\\.| |\\?|\\!|\\'"); 76 for (int i = 0; i < s.length; i++) { 77 if (s[i].length() >= 4) { 78 String temp = s[i].substring(0, 4); 79 temp = temp.replaceAll("[^a-zA-Z]", ""); 80 81 if (temp.length() >= 4) { 82 words++; 83 } 84 } 85 } 86 } 87 }catch (Exception e) { 88 System.out.println("读取文件内容出错"); 89 e.printStackTrace(); 90 } 91 return words; 92 } 93 /*统计最多的十个单词及其词频*/ 94 public static Map<String,String> countFrequency(String pathname){ 95 StringBuilder content = new StringBuilder(""); 96 Map<String,String> map = new HashMap<String,String>(); 97 try { 98 String encoding = "UTF-8"; 99 File file = new File(pathname); 100 if (file.isFile() && file.exists()) { 101 InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding); 102 /*读取文件数据*/ 103 StringBuffer sb=null; 104 BufferedReader br1; 105 try{ 106 br1=new BufferedReader(new FileReader(file)); 107 String temp=br1.readLine(); 108 sb=new StringBuffer(); 109 while(temp!=null){ 110 sb.append(temp); 111 temp=br1.readLine(); 112 } 113 } 114 catch (Exception e){ 115 e.printStackTrace(); 116 } 117 /*读取的内容*/ 118 String info=sb.toString(); 119 String s[]=info.split(",|\\.| |\\?|\\!|\\'"); 120 /*统计单词个数*/ 121 for(int i=0;i<s.length;i++){ 122 if(s[i].length()>=4) { 123 String temp = s[i].substring(0, 4); 124 temp=temp.replaceAll("[^a-zA-Z]", ""); 125 126 if (temp.length() >= 4) { 127 if (map.containsKey(s[i].toLowerCase())) {//判断Map集合对象中是否包含指定的键名 128 map.put(s[i].toLowerCase(), Integer.parseInt(map.get(s[i].toLowerCase())) + 1 + ""); 129 130 } else { 131 map.put(s[i].toLowerCase(), 1 + ""); 132 133 } 134 } 135 } 136 } 137 /*map排序*/ 138 map=sortMapByValue(map); 139 read.close(); 140 } else { 141 System.out.println("找不到指定的文件"); 142 } 143 } catch (Exception e) { 144 System.out.println("读取文件内容出错"); 145 e.printStackTrace(); 146 } 147 return map; 148 } 149 /*统计行数*/ 150 public static int countLines(String pathname) { 151 int lines = 0; 152 StringBuilder content = new StringBuilder(""); 153 try { 154 String encoding = "UTF-8"; 155 File file = new File(pathname); 156 if (file.isFile() && file.exists()) { 157 InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding); 158 BufferedReader br1; 159 try { 160 br1 = new BufferedReader(new FileReader(file)); 161 String temp = br1.readLine(); 162 while (temp != null) { 163 /*统计有效行数*/ 164 if (!temp.isEmpty()) { 165 lines++; 166 } 167 temp = br1.readLine(); 168 169 } 170 } catch (Exception e) { 171 e.printStackTrace(); 172 } 173 read.close(); 174 } else { 175 System.out.println("找不到指定的文件"); 176 } 177 } catch (Exception e) { 178 System.out.println("读取文件内容出错"); 179 e.printStackTrace(); 180 } 181 return lines; 182 183 } 184 /*生成新txt*/ 185 public static void printFile(int characters, int words, int lines, Map<String, String> map) { 186 StringBuilder content = new StringBuilder(""); 187 int count = 0; 188 while (count != 3) { 189 switch (count) { 190 case 0: 191 content.append("characters:"); 192 content.append(characters); 193 break; 194 case 1: 195 content.append("words:"); 196 content.append(words); 197 break; 198 case 2: 199 content.append("lines:"); 200 content.append(lines); 201 break; 202 } 203 count++; 204 content.append("\r\n"); 205 } 206 Set<String> keys = map.keySet(); 207 count = 1; 208 for (String key : keys) { 209 content.append("<" + key + ">:" + map.get(key)); 210 count++; 211 if (count > 10) 212 break; 213 content.append("\r\n"); 214 } 215 System.out.println(content); 216 BufferedWriter bw = null; 217 try { 218 String pathname = "./result.txt"; 219 File file = new File(pathname); 220 if (!file.exists()) { 221 file.createNewFile(); 222 } 223 FileWriter fw = new FileWriter(file.getAbsoluteFile()); 224 bw = new BufferedWriter(fw); 225 bw.write(content.toString()); 226 bw.close(); 227 } catch (IOException e) { 228 e.printStackTrace(); 229 } 230 } 231 /*map用value排序*/ 232 public static Map<String, String> sortMapByValue(Map<String, String> oriMap) { 233 if (oriMap == null || oriMap.isEmpty()) { 234 return null; 235 } 236 Map<String, String> sortedMap = new LinkedHashMap<String, String>(); 237 List<Map.Entry<String, String>> entryList = new ArrayList<Map.Entry<String, String>>( 238 oriMap.entrySet()); 239 Collections.sort(entryList, new MapValueComparator()); 240 241 Iterator<Map.Entry<String, String>> iter = entryList.iterator(); 242 Map.Entry<String, String> tmpEntry = null; 243 while (iter.hasNext()) { 244 tmpEntry = iter.next(); 245 sortedMap.put(tmpEntry.getKey(), tmpEntry.getValue()); 246 } 247 return sortedMap; 248 } 249 }
比较器MapValueComparator:
1 import java.util.Comparator; 2 import java.util.Map; 3 4 public class MapValueComparator implements Comparator<Map.Entry<String, String>> { 5 6 @Override 7 public int compare(Map.Entry<String, String> me1, Map.Entry<String, String> me2) { 8 int flag=me2.getValue().compareTo(me1.getValue()); 9 if(flag==0){ 10 flag=me1.getKey().compareTo(me2.getKey()); 11 } 12 return flag; 13 //return me1.getValue().compareTo(me2.getValue()); 14 } 15 }
计算模块接口部分的性能改进:
因为一开始写的时候比较随意,把几个统计方法都揉在一个方法里写了,这样复用效率不高,因此我将原先的大方法里的各个代码块独立出来,形成了最终的方法。并把开发过程中的一些冗余代码进行了删减。
计算模块部分单元测试展示:
测试用例
测试结果
计算模块部分异常处理说明:
通过try catch语句处理异常,在程序出错时方便查找出错点。当路径出错时,提示找不到指定文件;当无法打开文件时,提示无法打开文件。因为我对这方面知识较少,因此不太掌握这方面的知识,不是特别理解。
感想:
经过这次实践,我认识到了准备工作和自学能力的重要性。开始编写时没有做清楚计划,写完程序后代码揉成一团,之后找出关键语句单独封装耗费了很多时间。在开发过程中遇到很多复杂的问题,如果没有掌握自学能力的话学起来非常耗时且困难。第一次按照较规范化的格式编写代码,有很多地方代码冗余或者缺乏注释,我以后会逐渐改正的。