一.需求分析
根據實驗二軟件工程個人項目所提要求進行分析后可知用戶的需求主要有:
1.程序可讀入任意英文文本文件,該文件中英文詞數大於等於1個。
2.程序需要很壯健,能讀取容納英文原版《哈利波特》10萬詞以上的文章。
3.指定單詞詞頻統計功能:用戶可輸入從該文本中想要查找詞頻的一個或任意多個英文單詞,運行程序的統計功能可顯示對應單詞在文本中出現的次數和柱狀圖。
4.高頻詞統計功能:用戶從鍵盤輸入高頻詞輸出的個數k,運行程序統計功能,可按文本中詞頻數降序顯示前k個單詞的詞頻及單詞。
5.統計該文本所有單詞數量及詞頻數,並能將單詞及詞頻數按字典順序輸出到文件result.txt。
二.功能設計
基本功能
1.用戶輸入任意多個英文單詞,顯示對應單詞在文本中出現的次數和柱狀圖。
2.用戶從鍵盤輸入高頻詞輸出的個數k,按文本中詞頻數降序顯示前k個單詞的詞頻及單詞。
3.統計該文本所有單詞數量及詞頻數,並能將單詞及詞頻數按字典順序輸出到文件result.txt。
擴展功能
4.輸入一個文件的文件路徑及文件名可以找到該文件並對該文件中的文本進行單詞分解和單詞詞頻統計。
三.設計實現
在該詞頻統計軟件中,只有一個類Main.java,該類中在主函數main中用hashMap的數據結構、StringTokenizer方法來分詞並且統計詞頻;
在子函數queryWord中使用字符串的split分割方法以及字符串數組遍歷的方式找出用戶所需查詢的單詞對應的詞頻,通過保留各單詞詞頻占用戶查詢所有詞詞頻的比例來繪制響應的柱狀圖;
在子函數sortMapByValues中使用set、LinkedList及Entry等數據結構根據hashMap的值進行排序后根據用戶所輸入的k值輸出頻率最高的前K個單詞;
在子函數sortMapByKeys中使用與sortMapValues函數異曲同工的方式根據hashMap的鍵按照字母表順序進行排序后存放到當前目錄下的result.txt文件中;
最后在主函數中依次調用這三個子函數,實現所有具體功能。
四.測試運行
經過反復測試與調試之后的最終結果如下圖所示:
五.獨特代碼片段秀
分割文本中的單詞,統計相應詞頻
// 用正則表達式來過濾字符串中的所有標點符號
String regex = "[【】、.。,,。\"!--;:?\'\\]]";
try {
// 讀取要處理的文件
System.out.println("請輸入讀取文件的文件名:");
String s = in.nextLine();
BufferedReader br = new BufferedReader(new FileReader(s));
String value;
while ((value = br.readLine()) != null) {
value = value.replaceAll(regex, " ");
// 使用StringTokenizer來分詞
StringTokenizer tokenizer = new StringTokenizer(value);
while (tokenizer.hasMoreTokens()) {
String word = tokenizer.nextToken();
if (!hashMap.containsKey(word)) {
hashMap.put(word, new Integer(1));
} else {
int k = hashMap.get(word).intValue() + 1;
hashMap.put(word, new Integer(k));
}
}
}
對用戶輸入的字符串進行分割
System.out.println("請輸入需要查詢的單詞,單詞之間用空格隔開");
String s = in.nextLine();
String[] word= s.split(" ");
根據hashMap的值進行排序
Set<Entry<String,Integer>> mapEntries = Map.entrySet();
LinkedList<Entry<String, Integer>> List = new LinkedList<Entry<String,Integer>>(mapEntries);
// 根據映射的值對列表排序
Collections.sort(List, new Comparator<Entry<String,Integer>>() {
@Override
public int compare(Entry<String, Integer> ele1, Entry<String, Integer> ele2) {
return ele2.getValue().compareTo(ele1.getValue());
}
});
根據hashMap的鍵進行排序
Set<Entry<String,Integer>> mapEntries = Map.entrySet();
LinkedList<Entry<String, Integer>> List = new LinkedList<Entry<String,Integer>>(mapEntries);
// 根據映射的鍵對列表排序
Collections.sort(List, new Comparator<Entry<String,Integer>>() {
@Override
public int compare(Entry<String, Integer> ele1, Entry<String, Integer> ele2) {
return ele1.getKey().compareTo(ele2.getKey());
}
});
將排序好的單詞與詞頻的映射存放到文件中
File file = new File("result.txt");
try {
if(file.exists()) {
file.createNewFile();
}
FileWriter fop = new FileWriter(file.getAbsoluteFile());
for(Entry<String,Integer> entry : Map2.entrySet()) {
fop.write(entry.getKey()+":\t"+entry.getValue()+"\n");
}
fop.close();
System.out.println("存放結束,請在當前目錄下查看!");
}catch(IOException e) {
e.printStackTrace();
}
### 六.總結 在這次的詞頻統計軟件開發過程中,主要將該軟件分成三大模塊:文本的單詞提取和詞頻統計、單詞匹配后輸出、根據單詞詞頻排序后輸出用戶需要查看的k個、根據單詞字母表順序排序后保存在文件中。第一個模塊在主函數中實現,而后面三個模塊分別通過三個子函數來實現,之后在主函數中被調用,以此來達到軟件設計的“模塊化”原則。
### PSP展示
任務內容 | 計划共完成需要的時間(min) | 實際完成需要的時間(min) |
計划 | 8 | 5 |
估計這個任務需要的時間,並規划大致工作步驟 | 8 | 5 |
開發 | 100 | 105 |
需求分析(包括學習新技術) | 6 | 8 |
生成設計文檔 | 10 | 15 |
設計復審 | 6 | 5 |
代碼規范(為目前的開發制定合適的規范) | 3 | 3 |
具體設計 | 10 | 12 |
具體編碼 | 50 | 65 |
代碼復審 | 10 | 11 |
測試(自我測試、修改代碼、提交修改) | 15 | 17 |
報告 | 9 | 7 |
測試報告 | 3 | 3 |
計算報告量 | 1 | 2 |
事后總結,並提出過程改進計划 | 5 | 4 |