WordCount--實現字符,單詞,代碼統計


Github:

            https://github.com/whoNamedCody/WordCount

PSP表格 

PSP2.1

PSP階段

預估耗時

(分鍾)

實際耗時

(分鍾)

Planning

計划

            10            15

· Estimate

· 估計這個任務需要多少時間

            20            20

Development

開發

           180            250

· Analysis

· 需求分析 (包括學習新技術)

            10            30

· Design Spec

· 生成設計文檔

            10            20

· Design Review

· 設計復審 (和同事審核設計文檔)

            20               20

· Coding Standard

· 代碼規范 (為目前的開發制定合適的規范)

            10             20

· Design

· 具體設計

            20             20

· Coding

· 具體編碼

           100            150

· Code Review

· 代碼復審

            20            30

· Test

· 測試(自我測試,修改代碼,提交修改)

            50           100

Reporting

報告

            20            40  

· Test Report

· 測試報告

            30            40

· Size Measurement

· 計算工作量

            10            10

· Postmortem & Process Improvement Plan

· 事后總結, 並提出過程改進計划

             5            15
 

合計

           515           780

需求說明:

          WordCount的需求可以概括為:對程序設計語言源文件統計字符數、單詞數、行數,統計結果以指定格式輸出到默認文件中,以及其他擴展功能,並能夠快速地處理多個文件。

         1、基礎功能:

              -c:輸出字符,

              -l:輸出代碼行,

              -w:輸出單詞,

              -o:輸出

         2、 擴展功能:

              -a:輸出代碼行/空行/注釋行,

              -s:遞歸處理文件,

              -e:停用詞表,

 

解題思路:

           1、java實現,但需要轉成exe在cmd下輸入命令執行,所以流程是:編碼(.java)-->Export(.jar)-->exe4j(.exe)

           2、java里有static void main(String[] args),里面的args就是cmd下的命令數組,比如輸入-c -l -w file.c(空格隔開),那么args數組長度為4

           3、對args數組進行遍歷分析,找出輸入命令和文件名,比如-c -l -w -a 后面跟的是輸入文件名,-s后面會跟*.c之類的通配文件,-e后面會跟停用詞表stoplist.txt,-o接輸出文件result.txt

                這里識別出命令和文件后,會再對文件分析,比如-s  ./WordCount/*.c,需要截取出文件的上一層(相對)路徑./WordCount和后綴.c,方便后續遞歸文件夾下的.c文件

           4、將所有的統計封裝成一個函數:public void command(String[] args,String inputFile,String outputFile,WordCount WC)

           5、創建一個WordCount類,里面的屬性有字符數,單詞數,行數,代碼行,空行,注釋行,如果沒有出現-s:則只實例化一個對象WordCount,調用一次command函數,輸出前面的結果,如果出                           現 -s:即遞歸處理文件夾下面的*.c文件(當然*.txt,*.doc文件也是可以的),就聲明多個WordCount對象,循環對對象屬性進行賦值。如果需要輸出就調用get和set方法獲取屬性值。

           6、遞歸處理文件:根據相對路徑遞歸尋找文件夾下的后綴文件。

程序設計實現:

類:

                public class WordCount{}

函數方法設計:

        WordCount(int,int,int,int,int,int)是構造函數;get和set是MyEclipse自動生成的的getter和setter方法,main(string [ ])是程序入口,分析判斷指令格式;command(String [ ],String,String,WordCount)執行指令,返回相應指令的統計值;wc(String,String)對輸入文件進行統計;inStop(String,String[ ])判斷單詞是否在停用詞表內;getFile(File)遞歸獲取文件。

 

代碼說明:

   1、執行命令:需要輸出的有-c,-w,-l,-a,判斷指令,直接暴力循環,優化日后再說。

 1 //命令執行,根據命令輸出數據到屏幕和outputFile中    
 2     public void command(String[] args,String inputFile,String outputFile,WordCount WC)throws IOException{
 3         String outResult="";
 4         inputFile=inputFile.substring(inputFile.lastIndexOf("\\")+1, inputFile.length());
 5         for(int i=0;i<args.length;i++){
 6             if(args[i].equals("-c"))
 7                 outResult=outResult+inputFile+",字符數:" + WC.getCharCount()+"\r\n";
 8         }
 9         for(int i=0;i<args.length;i++){
10             if(args[i].equals("-w"))
11                 outResult=outResult+inputFile+",單詞數:" + WC.getWordCount()+"\r\n";
12         }
13         for(int i=0;i<args.length;i++){
14             if(args[i].equals("-l"))
15                 outResult=outResult+inputFile+",行數:" + WC.getLineCount()+"\r\n";
16         }
17         for(int i=0;i<args.length;i++){
18             if(args[i].equals("-a"))
19                 outResult=outResult+inputFile+",代碼行/空行/注釋行:"+WC.getCodeCount()+","
20                         +WC.getSpaceCount()+","+WC.getNoteCount()+"\r\n";
21         }
22         //寫數據到outputFile
23         System.out.println(outResult);        
24         File writename = new File(outputFile); 
25         writename.createNewFile(); 
26         BufferedWriter out = new BufferedWriter(new FileWriter(writename,true));
27         out.write(outResult);
28         out.flush();  
29         out.close(); 
30     }

 2、統計功能字符數、單詞數、行數、代碼行/空行/注釋行 

      提一下代碼行/空行/注釋行

      匹配空行的正則表達式或則判斷該行只有一個字符,則當前行為空行,匹配/*,如果存在,注釋行++,標志進入注釋行,繼續匹配*/,如果不存在,注釋行++,記下總共多少行,遇到*/,注釋行++,標志結束注       
      釋行,再匹配單行注釋,其他的是代碼行,最后計算注釋的時候要減去只有/*沒有 */的要加
 1 //統計功能字符數、單詞數、行數、代碼行/空行/注釋行    
 2     public void wc(String inputFile,String stopFile) throws IOException{
 3         String lineString = null; 
 4         String[] buffer=null; //文件每行
 5         String[] buffer1 = null;//stoplist
 6        
 7         boolean isNote = false;
 8         int notNote=0;
 9         
10         //讀取停用詞表
11         if(useStop){
12             File dirr=new File(stopFile);
13             BufferedReader bff = new BufferedReader(new FileReader(dirr));
14             while((lineString=bff.readLine())!=null){
15               buffer1=lineString.split(",| ");
16             }
17             bff.close();    
18         }
19         lineString = null;
20         
21        // 讀取輸入文件inputFile
22         File dir=new File(inputFile);
23         BufferedReader bf = new BufferedReader(new FileReader(dir));         
24         while((lineString=bf.readLine())!=null){
25  
26              //遇到 , 空格 就結束賦值
27             buffer=lineString.split(",| ");
28             for(int i=0;i<buffer.length;i++){
29                 
30                 //使用停用詞表則剔除詞表內單詞,不用則不踢
31                 if(useStop){
32                     if(!buffer[i].equals("")&&!inStop(buffer[i], buffer1)){
33                         wordCount++;
34                     }     
35                 }
36                 else{
37                     wordCount++;
38                 }
39                                
40             }
41             if(buffer.length!=1)
42                 lineCount++;
43             
44             charCount+=(lineString.length()+1);
45             
46             
47             lineString=lineString.trim();
48             //空行,一個字符的也算空行
49             if (lineString.matches("^[//s&&[^//n]]*$")||lineString.length()==1) {  
50                 spaceCount++;      
51             } 
52             //注釋/*的開始
53             else if (lineString.startsWith("/*") && !lineString.endsWith("*/")||((lineString.startsWith("{/*")
54                     ||lineString.startsWith("}/*"))&&!lineString.endsWith("*/"))){
55                  noteCount++;
56                  isNote=true;
57              }
58             //沒有遇到*/
59             else if(isNote&&!lineString.endsWith("*/")&&!lineString.startsWith("*/")) {  
60                 notNote++;
61                 noteCount++;
62             }
63             //遇到*/
64             else if (isNote == true && (lineString.endsWith("*/")||lineString.startsWith("*/"))) {
65                 noteCount++;
66                 isNote=false;
67             }
68             //注釋行
69             else if (lineString.startsWith("//")|| lineString.startsWith("}//")||lineString.startsWith("{//")||
70                     ((lineString.startsWith("{/*") ||lineString.startsWith("}/*")||lineString.startsWith("/*"))
71                             && lineString.endsWith("*/"))) { 
72                 noteCount++;
73             }
74             else{
75                 codeCount++;
76             }            
77             }
78             bf.close();
79             noteCount-=notNote;
80             codeCount+=notNote;
81     }
3、每次判斷單詞是否在停用詞表內
 1 //判斷是否在停用詞表內
 2 public static boolean inStop(String str,String[] buffer){
 3     int count=0;
 4     for(int i=0;i<buffer.length;i++){
 5         if(str.equals(buffer[i])){
 6             count++;
 7         }
 8     }
 9     if(count>0)
10         return true;
11     else
12         return false;
13 }

4、遍歷文件目錄,如-s ./test/*.c則遞歸遍歷./test目錄下的.c文件

 1 //遍歷目錄文件    
 2     public static List<File> getFile(File dir) {  
 3         List<File> files = new ArrayList<File>();
 4         // 此文件下的所有文件和文件夾集合
 5         File[] subs = dir.listFiles();   
 6         for (File file : subs) {  
 7             if (file.isFile() && file.getName().endsWith(endStr)) {
 8                 // 把獲取到的后綴文件添加到集合中,可以是任何后綴文件  
 9                 files.add(file); 
10             } else if (file.isDirectory()) 
11                 //如果是目錄,就進行遞歸
12                 files.addAll(getFile(file));   
13         }  
14         return files;  
15     }   

 

測試設計過程:

    設計測試用例的思路是采用白盒測試的語句覆蓋,盡可能把測試用例覆蓋所有可能的程序語句,當然特別是分支語句,會多做測試,如-s的是否遞歸處理文件在我的程序中是一個分支語句

      基本功能:

      1、測試-c:輸出file.c字符數

            wc.exe -c file.c  

 

       2、測試-c、-w、-l:輸出file.c字符數,單詞數、行數 (當前根目錄)   

           wc.exe -c -w -l file.c

  

       3、測試-w 、-l 、-c:輸出./testFile/file.c 字符數,單詞數、行數 (根目錄下其他路徑,命令順序)

           wc.exe -w -l -c ./testFile/file.c 

   

       4、測試-c 、-l 、-w、-o:輸出file.c字符數,單詞數、行數、輸出到文件resultAdd.txt

            wc.exe -c -l -w file.c -o resultAdd.txt

 

   

      擴展功能:

         5、測試-a:輸出file.c的代碼行/空行/注釋行

              wc.exe -a file.c

         6、測試-s、-a:輸出根目錄下所有.c文件的代碼行/空行/注釋行

              wc.exe -s -a *.c

      

          7、測試-e:測試停用詞表stoplist.txt

              wc.exe -w file.c -e stoplist.txt 

  

          8、測試-c、-w、-l 、-a、-o:輸出file.c字符數,單詞數、行數 、代碼行/空行/注釋行輸出到result.txt

              wc.exe -c -w -l -a file.c -o result.txt

   

         9、測試-a、-s、-e:測試遞歸,代碼行/空行/注釋行,停用詞表stoplist.txt 

           wc.exe -a -s ./testFile/*.c -e stoplist.txt

 

        10、測試-c、-w、-l、-a、-e、-o:對不遞歸進行測試

            wc.exe -c -w -l -a file.c -e stoplist.txt -o result.txt

 

        11、測試-c、-w、-l、-a、-s、-e、-o:覆蓋所有的指令測試

  

 

測試腳本

         點擊testScript.exe可以執行完11個測試用例,類似於批處理的方式,但只有一個進程,批處理測試用例。

          下面是java代碼,簡單敘述一下思路:創建一個進程打開之前的wc.exe,逐行讀取測試用例testCase.txt,一行是一條測試用例。

 

 1 package test;
 2 import java.io.BufferedInputStream;
 3 import java.io.BufferedReader;
 4 import java.io.File;
 5 import java.io.FileReader;
 6 import java.io.IOException;
 7 import java.io.InputStreamReader;
 8 import java.util.Scanner;
 9 
10 public class TestScript {
11          //進程p
12         static Process p;
13     public static void main(String[] args) throws IOException{
14         String lineString=null;
15         File dirr=new File("testCase.txt");  //測試用例文件
16         if(dirr.exists()){
17             BufferedReader bff = new BufferedReader(new FileReader(dirr));
18             while((lineString=bff.readLine())!=null){
19                 //非空行執行測試用例
20                 if(!lineString.trim().matches("^[//s&&[^//n]]*$")){
21                     System.out.println(lineString);
22                     command(lineString);
23                 }       
24             }
25             bff.close();
26         }else{
27             System.out.println("沒有該測試文件");
28         }
29         
30         Scanner sc = new Scanner(System.in);
31         String scc=sc.nextLine();
32     }
33     
34     public static void command(String cmd){
35         Runtime run = Runtime.getRuntime();//返回與當前 Java 應用程序相關的運行時對象  
36         try {  
37             p = run.exec(cmd);// 啟動另一個進程來執行命令  
38             BufferedInputStream in = new BufferedInputStream(p.getInputStream());  
39             BufferedReader inBr = new BufferedReader(new InputStreamReader(in));  
40             String lineStr;  
41             while ((lineStr = inBr.readLine()) != null)   
42                 System.out.println(lineStr);  
43             if (p.waitFor() != 0) {  
44                 if (p.exitValue() == 1)
45                     System.err.println("命令執行失敗!");  
46             }  
47             inBr.close();  
48             in.close();  
49         } catch (Exception e) {  
50             e.printStackTrace();  
51         }  
52     }
53     
54 }

 參考鏈接:

                      https://www.baidu.com

                      https://i.cnblogs.com/

                      https://bbs.csdn.net/

                      https://github.com/

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM