閱讀898 返回首頁    go 技術社區[雲棲]


Java正則表達式(三)、代碼量統計工具(統計java源文件中注釋、代碼、空白行數量)

       比如想統計一個Java程序員一天寫代碼的工作量(如:有效代碼多少行、空行多少、注釋多少行等),這個小工具也許能做為一個參考的依據。

    思路:因為每個java源文件的內容基本包括java語句、空白行、注釋三部份組成(不包括注解),所以要統計某個文件這三部份的內容各占多少時,隻需寫三個匹配這幾部份內容的正則表達式即可。然後通過IO流讀取文件中的每一行,並根據正則匹配的結果,累加每部份匹配的數量即可。

    注釋行:單行注釋(//)、多行注釋、文檔注釋。正則:((//)|(/\\*+)|((^\\s)*\\*)|((^\\s)*\\*+/))+

    空白行:一行內隻有空格、\t、\n等非可視字符表示空白行。正則:^\\s*$

    代碼行:以分號“;“結束為一行有效的代碼。正則:(?!import|package).+;\\s*(((//)|(/\\*+)).*)*

    實現方式:

        1、用戶在控製台輸入要統計的java文件路徑或目錄

        2、根據路徑創建一個File對象,判斷文件是否有效,並給出提示。最後將文件和IO流綁定

        3、循環讀取文件中的某一行,並根據正則匹配的結果累記每部份匹配的數量


完整代碼如下:
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 FileNotFoundException(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("關閉文件輸入流失敗!");
				}
			}
		}
	}
}
測試結果:


最後更新:2017-04-02 16:47:46

  上一篇:go JavaMail學習筆記(七)、帳號激活與忘記密碼 實例
  下一篇:go android客戶端加密代碼