201671030128+词频统计软件项目报告
一.需求分析
根据实验二 软件工程个人项目的要求本次软件项目的需求有以下几点:
1.程序可读入任意英文文本文件,该文件中英文词数大于等于1个,程序需要很壮健,能读取容纳英文原版《哈利波特》10万词以上的文章。
2.指定单词词频统计功能:用户可输入从该文本中想要查找词频的一个或任意多个英文单词,运行程序的统计功能可显示对应单词在文本中出现的次数和柱状图。
3.高频词统计功能:用户从键盘输入高频词输出的个数k,运行程序统计功能,可按文本中词频数降序显示前k个单词的词频及单词。
4.统计该文本所有单词数量及词频数,并能将单词及词频数按字典顺序输出到文件result.txt。
二.功能设计
1.对于需求1、需求4需要有读入文本数据、向文本输出数据的功能。
2.对于需求3和需求4需要有排序的功能
3.整个项目要求有对词频进行统计的功能
三.设计实现
1.本次项目有两个类:
(1)main.java主要实现文本读入和功能选择的功能,根据用户输入的选择调用function.java中相应的功能函数。
(2)function.java实现排序(sort函数),查找单词词频显示柱状图(find函数),输出前n个高频词(print函数),单词及词频数按字典顺序输出到文件result.txt(Sort函数)四个主要功能。
2.数据结构:
本次项目采用TreeMap存储从文本读入的数据,用LinkedList进行词频排序。
3.流程图:
本项目总的流程图为:
四.测试运行
1.显示单词词频和柱状图
2.输出前K个高频词
3.向result.txt写入单词和词频
五.主要代码
1.文件读入并统计词频
// 读取要处理的文件
BufferedReader b = new BufferedReader(new FileReader("src/HarryPotter.txt"));
//<单词:词频>
Map<String, Integer> map = new TreeMap<String, Integer>();
String value= b.readLine();
while (value!= null) {
//处理标点符号
String[] words = value.split("[【】、.。,\"!--;:?\'\\] ]");
for (int i = 0; i < words.length; i++) {
//将大写字母转换为小写字母
String key = words[i].toLowerCase();
if (key.length() > 0) {
if (!map.containsKey(key)) {
map.put(key, 1);
}
else {
int k = map.get(key)+1;// 如果不是第一次出现,就把k值++
map.put(key, k);
}
}
}
value = b.readLine();
}
2.按词频或字母排序
Set<Entry<String,Integer>> m= map.entrySet();
LinkedList<Entry<String, Integer>> List = new LinkedList<Entry<String,Integer>>(m);
//按值排序
if(a==2) {
Collections.sort(List, new Comparator<Entry<String,Integer>>() {
public int compare(Entry<String, Integer> a, Entry<String, Integer> b) {
return b.getValue().compareTo(a.getValue());
}
});
//按键排序
else if(a==3) {
Collections.sort(List, new Comparator<Entry<String,Integer>>() {
public int compare(Entry<String, Integer> a, Entry<String, Integer> b) {
return a.getKey().compareTo(b.getKey());
}
});
}
//排序后存入Map中
for(Entry<String,Integer> entry: List) {
Map.put(entry.getKey(), entry.getValue());
}
}
3.向文件写入单词词频
//创建文件
File file = new File("result.txt");
//向文件写入
FileWriter f = new FileWriter(file.getAbsoluteFile());
for(Entry<String,Integer> w: Map.entrySet()) {
f.write(w.getKey() + "/" + w.getValue()+" ");
}
f.close();
System.out.println("结束!");
六.总结
1.本次项目中各功能在function类中,用函数实现各个功能,通过用户输值调用相应的功能,以此来实现模块化。
2.在刚开始设计读入文件数据的时候,打算采用二维数组存放单词,相应的一维数组存放个数,但发现数组太大,而且在进行排序的时候不方便因此采用了<键:值>的映射存放数据。
3.在进行柱状图绘制时,由于除以500后的小数无法表示,只能表示出大概的趋势。
七.PSP
任务内容 | 计划完成时间(min) | 实际完成时间(min) |
---|---|---|
计划 | 5 | 3 |
规划工作步骤 | 10 | 7 |
开发 | 173 | 202 |
需求分析 | 10 | 15 |
生成文档 | 5 | 10 |
设计复审 | 3 | 2 |
代码规范 | 20 | 15 |
具体编码 | 100 | 120 |
代码复审 | 10 | 5 |
测试 | 25 | 40 |
报告 | 15 | 12 |
测试报告 | 5 | 7 |
计算报告量 | 5 | 2 |
事后总结 | 5 | 3 |
从表中可以看出在编码阶段时间较多且和自己估计的时间差距较大,主要是在进行数据结构的选择上错误,浪费大量时间进行修改,并且由于长时间没有使用Java,所有有些生疏,在测试阶段时间也比较长,自己开始的逻辑上有些混乱导致结果不正确显示,一步步的调试最终实现了相应功能。 | ||
点击源码可查看项目源代码 |