首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 統計專案程式碼行數:總行、程式碼行、註解行、空白行

     編輯:Java 相關知識

需求

掃描專案目錄下所有 `.java` 檔案,統計四類行數:

  • **總行數** — 檔案實際行數
  • **程式碼行** — 非空白、非純註解的有效程式碼
  • **註解行** — 單行 `//`、多行 `/* */`、Javadoc `/** */`
  • **空白行** — 完全無字元或僅含空白字元

完整統計工具類


import java.io.*;
import java.nio.file.*;
import java.util.concurrent.atomic.AtomicLong;

public class CodeLineCounter {
    private final AtomicLong totalLines = new AtomicLong();
    private final AtomicLong codeLines = new AtomicLong();
    private final AtomicLong commentLines = new AtomicLong();
    private final AtomicLong blankLines = new AtomicLong();

    public static void main(String[] args) throws IOException {
        String rootPath = args.length > 0 ? args[0] : System.getProperty("user.dir");
        CodeLineCounter counter = new CodeLineCounter();
        counter.scan(Paths.get(rootPath));
        counter.printReport();
    }

    public void scan(Path root) throws IOException {
        Files.walkFileTree(root, new SimpleFileVisitor() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                if (file.toString().endsWith(".java")) {
                    countFile(file);
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }

    private void countFile(Path file) {
        try (BufferedReader br = Files.newBufferedReader(file, java.nio.charset.StandardCharsets.UTF_8)) {
            boolean inBlockComment = false;
            String line;
            while ((line = br.readLine()) != null) {
                totalLines.incrementAndGet();
                String trimmed = line.trim();

                // 空白行
                if (trimmed.isEmpty()) {
                    blankLines.incrementAndGet();
                    continue;
                }

                // 處理區塊註解狀態
                if (inBlockComment) {
                    commentLines.incrementAndGet();
                    if (trimmed.endsWith("*/")) inBlockComment = false;
                    continue;
                }

                // 單行註解
                if (trimmed.startsWith("//")) {
                    commentLines.incrementAndGet();
                    continue;
                }

                // 區塊註解開始
                if (trimmed.startsWith("/*")) {
                    commentLines.incrementAndGet();
                    if (!trimmed.endsWith("*/")) inBlockComment = true; // 跨行
                    continue;
                }

                // 正常程式碼行 (可能包含行尾註解,這裡簡單計為程式碼)
                codeLines.incrementAndGet();
            }
        } catch (IOException e) {
            System.err.println("讀取失敗: " + file + " - " + e.getMessage());
        }
    }

    private void printReport() {
        System.out.println("================== 程式碼統計報表 ==================");
        System.out.printf("掃描目錄: %s%n", System.getProperty("user.dir"));
        System.out.printf("總行數     : %,d%n", totalLines.get());
        System.out.printf("程式碼行   : %,d%n", codeLines.get());
        System.out.printf("註解行     : %,d%n", commentLines.get());
        System.out.printf("空白行     : %,d%n", blankLines.get());
        System.out.println("==================================================");
        long sum = codeLines.get() + commentLines.get() + blankLines.get();
        System.out.printf("驗證總和   : %,d (差異: %,d)%n", sum, totalLines.get() - sum);
    }
}

執行方式


# 編譯
javac CodeLineCounter.java

# 執行 (掃描當前目錄)
java CodeLineCounter

# 指定目錄
java CodeLineCounter /path/to/project/src

輸出範例

================== 程式碼統計報表 ==================
掃描目錄: /home/user/my-project
總行數     : 125,430
程式碼行   : 78,210
註解行     : 22,150
空白行     : 25,070
==================================================
驗證總和   : 125,430 (差異: 0)

演算法細節與限制

進階:使用 JavaParser 精確解析 (Maven)



    com.github.javaparser
    javaparser-core
    3.25.0


// 精確統計:AST 解析,完全忽略字串內註解符號
CompilationUnit cu = StaticJavaParser.parse(file);
long commentLines = cu.getAllContainedComments().stream()
    .map(c -> c.getEnd().get().line - c.getBegin().get().line + 1)
    .mapToLong(Long::longValue).sum();
// 程式碼行 = 總行 - 註解行 - 空白行 (需自行計算)

生產級替代工具

  • 🛠 cloc (Count Lines of Code) — 多語言、極快、CLI 一鍵:`cloc --include-lang=Java src/`
  • 🛠 SonarQube — 持續檢測、儀表板、技術債務、重複率
  • 🛠 IntelliJ IDEA — `Analyze` → `Calculate Metrics` 內建統計

自寫統計器適合輕量級需求、嵌入 CI 腳本、教學理解;大型專案建議接入 cloc 或 SonarQube 獲得多維度度量。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
項目處理方式已知限制
單行註解 //trim() 後 startsWith("//")字串字面值內的 // 會誤判
多行註解 /* */狀態機 inBlockComment巢狀註解不支援 (Java 不允許)
Javadoc /** */同多行註解處理同上
字串/字元常值未剝離,可能誤判裡面的註解符號需完整語法分析器 (如 JavaParser) 解決
編碼預設 UTF-8舊專案可能為 GBK/Big5,需自行調整