Java正則表達式(三)、代碼量統計工具(統計java源文件中註釋、代碼、空白行數量) – JAVA編程語言程序開發技術文章

思路:因為每個java源文件的內容基本包括java語句、空白行、註釋三部份組成(不包括註解),所以要統計某個文件這三部份的內容各占多少時,隻需寫三個匹配這幾部份內容的正則表達式即可。然後通過IO流讀取文件中的每一行,並根據正則匹配的結果,累加每部份匹配的數量即可。
    註釋行:單行註釋(//)、多行註釋、文檔註釋。正則:((//)|(/\\*+)|((^\\s)*\\*)|((^\\s)*\\*+/))+
    空白行:一行內隻有空格、\t、\n等非可視字符表示空白行。正則:^\\s*$
    代碼行:以分號“;“結束為一行有效的代碼。正則:(?!import|package).+;\\s*(((//)|(/\\*+)).*)*
    實現方式:
        1、用戶在控制臺輸入要統計的java文件路徑或目錄
        2、根據路徑創建一個File對象,判斷文件是否有效,並給出提示。最後將文件和IO流綁定
        3、循環讀取文件中的某一行,並根據正則匹配的結果累記每部份匹配的數量

完整代碼如下:
[java] 
package regex; 
 
import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileFilter; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.Scanner; 
import java.util.regex.Pattern; 
 
/**
 * 代碼統計工具
 * 統計某個java源文件或某個目錄中所有java源文件中註釋、空白行、代碼行各占多少行
 * 註釋:包括單行註釋(//)、多行註釋、文檔註釋
 * 空白行:一行內沒有任何內容的表示空白行
 * 代碼行:以分號“;”結束的一條語句,可以統計為一行有效代碼
 */ 
public class CodeStatDemo { 
     
    // 記錄註釋行數 
    static long annotationLine = 0; 
     
    // 記錄空白行數 
    static long blankLine = 0; 
     
    // 記錄有效代碼的行數 
    static long codeLine = 0; 
     
    // 代碼總行數 
    static long totalLine = 0; 
     
    // 文件總數 
    static long fileCount = 0; 
 
    public static void main(String[] args) throws FileNotFoundException  { 
        System.out.println("請輸入要統計代碼量的java文件或java目錄:"); 
        Scanner in = new Scanner(System.in); 
        String filePath = in.nextLine(); 
         
        File file = new File(filePath); 
        // 根據用戶輸入的文件名和目錄執行代碼量統計 
        codeStat(file); 
         
        System.out.println("----------統計結果---------"); 
        System.out.println("文件數量:" + fileCount + "個"); 
        System.out.println(file + "文件/目錄總行數:" + totalLine); 
        System.out.println("代碼行數:" + codeLine); 
        System.out.println("註釋行數:" + annotationLine); 
        System.out.println("空白行數:" + blankLine); 
        long otherLine = totalLine – (codeLine + annotationLine + blankLine); 
        System.out.println("其它行數:" + otherLine); 
         
    } 
 
    private static void codeStat(File file) throws FileNotFoundException { 
        if (file == null || !file.exists())  
            throw new FileNotFoundException(file + ",文件不存在!"); 
         
        fileCount ++;   // 文件數累加 
         
        if (file.isDirectory()) { 
            File[] files = file.listFiles(new FileFilter() { 
                 
                @Override 
                public boolean accept(File pathname) { 
                    return pathname.getName().endsWith(".java") || pathname.isDirectory(); 
                } 
            }); 
             
            for (File target : files) { 
                codeStat(target); 
            } 
        } else { 
            BufferedReader bufr = null; 
            try { 
                // 將指定路徑的文件與字符流綁定 
                bufr = new BufferedReader(new InputStreamReader(new FileInputStream(file))); 
            } catch (FileNotFoundException e) { 
                throw new RuntimeException(file + ",文件不存在!" + e); 
            } 
             
            // 定義匹配每一行的正則匹配器 
            Pattern annotationLinePattern = Pattern.compile("((//)|(/\\*+)|((^\\s)*\\*)|((^\\s)*\\*+/))+",  
                    Pattern.MULTILINE + Pattern.DOTALL);    // 註釋匹配器(匹配單行、多行、文檔註釋) 
             
            Pattern blankLinePattern = Pattern.compile("^\\s*$");   // 空白行匹配器(匹配回車、tab鍵、空格) 
             
            Pattern codeLinePattern = Pattern.compile("(?!import|package).+;\\s*(((//)|(/\\*+)).*)*", 
                    Pattern.MULTILINE + Pattern.DOTALL); // 代碼行匹配器(以分號結束為一行有效語句,但不包括import和package語句) 
             
            // 遍歷文件中的每一行,並根據正則匹配的結果記錄每一行匹配的結果 
            String line = null; 
            try { 
                while((line = bufr.readLine()) != null) { 
                    if (annotationLinePattern.matcher(line).find()) { 
                        annotationLine ++; 
                    } 
                     
                    if (blankLinePattern.matcher(line).find()) { 
                        blankLine ++; 
                    } 
                     
                    if (codeLinePattern.matcher(line).matches()) { 
                        codeLine ++; 
                    }  
                     
                    totalLine ++; 
                } 
                 
            } catch (IOException e) { 
                throw new RuntimeException("讀取文件失敗!" + e); 
            } finally { 
                try { 
                    bufr.close();   // 關閉文件輸入流並釋放系統資源 
                } catch (IOException e) { 
                    throw new RuntimeException("關閉文件輸入流失敗!"); 
                } 
            } 
        } 
    } 

測試結果:

作者:xyang81

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。