軟件工程:java實現wordcount基本功能
github鏈接:https://github.com/Nancy0611/wc
一:項目相關要求
該項目能統計文本文件的字符數、單詞數和行數。這個項目要求寫一個命令行程序,模仿已有wc.exe 的功能,並加以擴充,給出某程序設計語言源文件的字符數、單詞數和行數。實現一個統計程序,它能正確統計程序文件中的字符數、單詞數、行數,以及還具備其他擴展功能,並能夠快速地處理多個文件。
程序處理用戶需求的模式為:wc [parameter] [file_name]
二:項目功能完成情況
基本功能:
- wc -c <file> 統計文件的字符數(完成)
- wc -w <file> 統計文件詞的數目(完成)
- wc -l <file> 統計文件的行數 (完成)
擴展功能:
- wc -s <file> 遞歸處理目錄下符合條件的文件(已完成)
- wc -a <file> 返回更復雜的數據:代碼行 / 空行 / 註釋行(已完成)
說明:
空行:本行全部是空格或格式控制字符,如果包括代碼,則只有不超過一個可顯示的字符,例如“{”。
代碼行:本行包括多於一個字符的代碼。
註釋行:本行不是代碼行,並且本行包括註釋。一個有趣的例子是有些程序員會在單字符後面加註釋:} //註釋,在這種情況下,這一行屬於註釋行。
高級功能:
-
wc -x [parameter] 這個參數單獨使用。如果命令行有這個參數,則程序會顯示圖形界面,用戶可以通過界面選取單個文件,程序就會顯示文件的字符數、行數等全部統計信息。(未完成)
三:設計思路
-
獲取輸入命令行參數,利用正則表達式校驗輸入命令行是否符合格式
-
如果輸入命令符合格式要求則利用split(" ")按照空格將命令拆開並存儲於數組
-
獲取命令數組的最後一個元素,即為待統計的文件名或目錄
-
若輸入為文件則直接進行統計,若輸入為目錄則通過遞歸處理目錄下的文件
-
輸入參數[-c] [-w] [-l] [-a] 初始值設為false,一旦輸入將值置為true以此選擇性地顯示
-
根據不同的命令對數據進行相應的處理
-
-
字符數:獲取每行的字符數,逐行疊加
- 詞的數目:獲取每行除去空格的字符數,逐行疊加
-
行數:利用readline()不為 null,逐行疊加
- 空行:利用正則表達式統計只含"{"或 "}"或 "\n"的行數
-
註釋行:統計除去"//"、"{//"、"/*"開頭、"*/"結尾、"/* 單行註釋 */"、"/*多行註釋*/"
- 代碼行:總行數除去代碼行和空行即可得
-
四:設計思路
五:代碼說明
程序入口,獲取輸入命令行,檢驗後若符合格式,則將命令解析並調用相關功能函數
1 public static void main(String[] args) throws IOException { 2 3 scan = new Scanner(System.in); 4 String commend=scan.nextLine(); 5 boolean result=checkInput(commend); 6 //輸入格式為:wc [parameter] [file_name] 7 8 if(!result){ 9 System.out.println("輸入指令不符格式"); 10 }else{ 11 String[] comArray=commend.split(" "); 12 int comLength=comArray.length; 13 String File_name=comArray[comLength-1];//獲取文件名 14 ArrayList<File> ff = new ArrayList<File>(); 15 getFromFile_name(File_name); 16 17 for(File perfile:file){ 18 br=new BufferedReader(new FileReader(perfile)); 19 countData(br); 20 } 21 status(comArray,comLength);//修改cwl狀態 22 display(c,w,l,a);//顯示 23 br.close(); 24 } 25 }
正則表達式檢驗輸入命令行格式
1 public static boolean checkInput(String input){//正則表達式校驗輸入命令行 2 boolean flag=false; 3 try{ 4 String pattern="^wc\\s+(\\-[cwlas]\\s+){1,5}\\s*\\S+$"; 5 Pattern regex=Pattern.compile(pattern); 6 Matcher matcher=regex.matcher(input); 7 flag=matcher.matches(); 8 }catch(Exception e){ 9 flag=false; 10 } 11 return flag; 12 }
根據輸入文件名或文件路徑獲取文件
1 public static ArrayList<File> getFromFile_name(String path){ 2 File f=new File(path); 3 file=new ArrayList<File>(); 4 if(f.isFile()&&f.exists()){ 5 file.add(f); 6 }else if(f.isDirectory()){ 7 File[] files=f.listFiles(); 8 for(File fis: files){ 9 if(fis.isFile()){//文件 10 file.add(fis); 11 }else if(fis.isDirectory()){//目錄 12 //System.out.println(fis.getAbsolutePath()); 13 getFromFile_name(fis.getAbsolutePath()); 14 } 15 } 16 } 17 return file; 18 }
根據輸入命令行的解析結果修改c w l a的狀態,輸入含有以上字符則標記為true
1 public static void status(String[] comArray,int comLength){//修改cwla狀態 2 for(int i=0;i<comLength;i++){ 3 switch(comArray[i]){ 4 case "-c": 5 c=true; 6 break; 7 8 case "-w": 9 w=true; 10 break; 11 12 case "-l": 13 l=true; 14 break; 15 16 case "-a": 17 a=true; 18 break; 19 20 default: 21 break; 22 } 23 } 24 }
根據標記的c w l a的值來選擇顯示的內容
1 public static void display( boolean c,boolean w,boolean l,boolean a){ 2 //選擇顯示部分 3 if(c){ 4 System.out.println("字符數:"+countChar); 5 } 6 if(w){ 7 System.out.println("詞的數目:"+countWord); 8 } 9 if(l){ 10 System.out.println("行數:"+countLine); 11 } 12 if(a){ 13 System.out.println("代碼行:"+codeLine+"\n空行:"+blankLine+"\n註釋行:"+commentLine); 14 } 15 }
計算功能
1 public static void countData(BufferedReader br){//計算部分 2 boolean comment=false; 3 try { 4 while((line=br.readLine())!=null){ 5 /*統計字符數 */ 6 countChar+=line.length(); 7 /*統計詞的數目 */ 8 countWord+=line.split(" ").length; 9 /*統計行數 */ 10 countLine++; 11 line=line.trim(); 12 /* 統計空行*/ 13 if(line.matches("[\\s&&[^\\n]]*$")){ 14 blankLine++; 15 }else if(line.equals("{")||line.equals("}")){ 16 blankLine++; 17 /* 統計註釋行 */ 18 }else if(line.startsWith("/*")&&!line.endsWith("*/")){ 19 commentLine++; 20 comment=true; 21 }else if(true==comment){ 22 commentLine++; 23 if(line.endsWith("*/")){ 24 comment=false; 25 } 26 }else if(line.startsWith("//")){ 27 commentLine++; 28 }else if(line.startsWith("/*")&&line.endsWith("*/")){ 29 commentLine++; 30 }else if(line.startsWith("}//")){ 31 commentLine++; 32 /*統計代碼行 */ 33 }else{ 34 codeLine++; 35 } 36 } 37 38 } catch (IOException e) { 39 // TODO Auto-generated catch block 40 e.printStackTrace(); 41 } 42 43 }
六:測試截圖
- 根據文件名統計(非遞歸)
輸入命令
wc -c -l -w -a E:\test\test1.txt
文件截圖:
測試結果:
- 根據文件路徑統計(遞歸處理)
輸入命令:
wc -s -c -l -w -a E:\test
文件截圖:
E:\test\test1.txt
E:\test\seles\test2.txt
測試結果:
七:PSP時間統計
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 30 | 80 |
· Estimate | · 估計這個任務需要多少時間 | 200 | 300 |
Development | 開發 | 180 | 210 |
· Analysis | · 需求分析 (包括學習新技術) | 20 | 30 |
· Design Spec | · 生成設計文檔 | 10 | 15 |
· Design Review | · 設計復審 (和同事審核設計文檔) | 10 | 10 |
· Coding Standard | · 代碼規範 (為目前的開發制定合適的規範) | 15 | 15 |
· Design | · 具體設計 | 30 | 45 |
· Coding | · 具體編碼 | 160 | 190 |
· Code Review | · 代碼復審 | 20 | 20 |
· Test | · 測試(自我測試,修改代碼,提交修改) | 20 | 20 |
Reporting | 報告 | 60 | 80 |
· Test Report | · 測試報告 | 10 | 10 |
· Size Measurement | · 計算工作量 | 10 | 10 |
· Postmortem & Process Improvement Plan | · 事後總結, 並提出過程改進計劃 | 20 | 20 |
合計 | 795 | 1055 |
八:項目總結
關於wordcount,首先,一開始的構思是先讀取文件,一段時間沒有使用java,對io流的相關內容不是很熟悉,成功將文件存進ArrayList中後我沒有考慮到Array List變量之間的賦值問題,直接用=去賦值,發現取出的數據出錯,經過上網搜索了解了關於ArrayList對象之間賦值該註意的問題,收獲不少。其次,對輸入指令格式的驗證問題,由於之前沒有接觸過正則表達式,在正則表達式的相關內容上花費了挺多時間。最後,關於項目編程還是要多實踐,本次課程設計一開始都是停留在想的階段,一直沒怎麽實踐,結果發現過去了挺長時間仍舊沒有進度。經過這次課程設計,溫習了java的相關內容,同時又發現了許多新的問題,在解決問題的過程受益匪淺。
軟件工程:java實現wordcount基本功能