根據實驗二軟件工程我的項目所提要求進行分析後可知用戶的需求主要有:
1.程序可讀入任意英文文本文件,該文件中英文詞數大於等於1個。
2.程序須要很壯健,能讀取容納英文原版《哈利波特》10萬詞以上的文章。
3.指定單詞詞頻統計功能:用戶可輸入從該文本中想要查找詞頻的一個或任意多個英文單詞,運行程序的統計功能可顯示對應單詞在文本中出現的次數和柱狀圖。
4.高頻詞統計功能:用戶從鍵盤輸入高頻詞輸出的個數k,運行程序統計功能,可按文本中詞頻數降序顯示前k個單詞的詞頻及單詞。
5.統計該文本全部單詞數量及詞頻數,並能將單詞及詞頻數按字典順序輸出到文件result.txt。
html
基本功能
1.用戶輸入任意多個英文單詞,顯示對應單詞在文本中出現的次數和柱狀圖。
2.用戶從鍵盤輸入高頻詞輸出的個數k,按文本中詞頻數降序顯示前k個單詞的詞頻及單詞。
3.統計該文本全部單詞數量及詞頻數,並能將單詞及詞頻數按字典順序輸出到文件result.txt。
擴展功能
4.輸入一個文件的文件路徑及文件名能夠找到該文件並對該文件中的文本進行單詞分解和單詞詞頻統計。
java
在該詞頻統計軟件中,只有一個類Main.java,該類中在主函數main中用hashMap的數據結構、StringTokenizer方法來分詞而且統計詞頻;
在子函數queryWord中使用字符串的split分割方法以及字符串數組遍歷的方式找出用戶所需查詢的單詞對應的詞頻,經過保留各單詞詞頻佔用戶查詢全部詞詞頻的比例來繪製響應的柱狀圖;
在子函數sortMapByValues中使用set、LinkedList及Entry等數據結構根據hashMap的值進行排序後根據用戶所輸入的k值輸出頻率最高的前K個單詞;
在子函數sortMapByKeys中使用與sortMapValues函數殊途同歸的方式根據hashMap的鍵按照字母表順序進行排序後存放到當前目錄下的result.txt文件中;
最後在主函數中依次調用這三個子函數,實現全部具體功能。
git
通過反覆測試與調試以後的最終結果以下圖所示:
github
分割文本中的單詞,統計相應詞頻正則表達式
// 用正則表達式來過濾字符串中的全部標點符號 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的鍵進行排序ide
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個、根據單詞字母表順序排序後保存在文件中。第一個模塊在主函數中實現,然後面三個模塊分別經過三個子函數來實現,以後在主函數中被調用,以此來達到軟件設計的「模塊化」原則。
函數
任務內容 | 計劃共完成須要的時間(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 |
從PSP表中能夠看出在具體編碼這一環節耗時最多並且計劃時間和實際時間之間的差距比較大,這是由於好久沒有練習,須要在網上和教材上搜集相關知識點並重溫,因此耗時較多。所以在後面的學習中,還須要勤加練習,更加熟練的掌握知識點,而後更好的運用到本身的學習當中。
該詞頻統計軟件源碼可在此處查看