1.各種行的說明
在Java源程序中的行共有3種:
(1)代碼行,可運行的Java源代碼。例如:
1 int n = 10;
(2) 注釋行,3種注釋均可。例如:
1 /** 2 文檔注釋 3 */ 4 5 /* 6 多行注釋 7 */ 8 9 //單行注釋
(3)空行,既無代碼,也無注釋;
1
2.特殊行的處理方法
如果有以下行尾單行注釋的情況,將該行判定為代碼行。
1 int number; //number表示人數 2 int n; /*n表示數量*/
如果有以下行尾多行注釋的情況,第1行判定為代碼行,第二行判定為注釋行。
1 int number; /* number為整型 2 表示人數 */
假設被分析程序源碼無其他特殊情況,如:
1 int /*人數*/ number;
代碼實現
代碼中不使用正則表達式進行簡化操作,而是使用邏輯判斷.
思路還是先在給定的目錄下遞歸尋找所有的java文件,將其加入到ArrayList中.用循環對ArrayList中每一個java文件分別統計總行數,注釋行數,空白行數,代碼行數.雖然可以只掃描一遍文件就能得到不同的行數,但是為了代碼的耦合度和美觀,每個統計都分開一個方法.
構造方法
1 ArrayList<File> fileList; 2 File root; 3 public CodeAnalyzer(String pathName) { 4 root = new File(pathName); //給定的目錄 5 fileList = new ArrayList<>(); //儲存java文件 6 }
遞歸搜索目錄下的java文件
1 public void searchFiles() { 2 File[] files = root.listFiles(); 3 int length = files.length; 4 for (int i = 0; i < length; i++) { 5 if (files[i].isDirectory()) { 6 root = files[i]; 7 searchFiles(); 8 } else { 9 if (files[i].getName().endsWith(".java")) 10 fileList.add(files[i]); 11 } 12 } 13 }
統計單個文件的空白行數
1 public int countBlanks(File file) throws IOException { 2 BufferedReader input = new BufferedReader(new FileReader(file)); 3 int blanks = 0; 4 String line = null; 5 while ((line = input.readLine()) != null) { 6 if (line.trim().equals("")) blanks++; 7 } 8 return blanks; 9 }
統計單個文件的注釋行數
1 public int countComments(File file) throws IOException { 2 BufferedReader input = new BufferedReader(new FileReader(file)); 3 int comments = 0; 4 String line = null; 5 while ((line = input.readLine()) != null) { 6 line = line.trim(); 7 if (line.startsWith("//")) { //單行注釋 8 comments++; 9 } else if (line.startsWith("/*")) { //多行及文檔注釋 10 comments++; 11 while (!line.endsWith("*/")) { 12 line = input.readLine().trim(); 13 comments++; 14 } 15 } else if (line.contains("/*")) { //行尾多行注釋 16 line = input.readLine().trim(); 17 if (line.endsWith("*/")) comments++; 18 } 19 } 20 return comments; 21 }
總的統計與輸出
1 public void codeAnalyze() { 2 double rowsCount = 0; 3 double commentsCount = 0; 4 double blanksCount = 0; 5 double codesCount = 0; 6 DecimalFormat df = new DecimalFormat("#.##"); 7 for (File file : fileList) { 8 try { 9 rowsCount += countRows(file); 10 blanksCount += countBlanks(file); 11 commentsCount += countComments(file); 12 codesCount = rowsCount - blanksCount - commentsCount; 13 } catch (IOException e) { 14 e.printStackTrace(); 15 } 16 } 17 //輸出結果 18 System.out.println("源程序文件總行數:" + (int) rowsCount); 19 System.out.println("代碼行數:" + (int) codesCount + ",占" + df.format(codesCount / rowsCount*100) + "%"); 20 System.out.println("注釋行數:" + (int) commentsCount + ",占" + df.format(commentsCount / rowsCount*100) + "%"); 21 System.out.println("空白行數:" + (int) blanksCount + ",占" + df.format(blanksCount / rowsCount*100) + "%"); 22 }
主函數
1 public static void main(String[] args) { 2 String pathName = "E:\\1"; 3 CodeAnalyzer analyzer = new CodeAnalyzer(pathName); 4 analyzer.searchFiles(); //搜索文件 5 analyzer.codeAnalyze(); //統計文件 6 }
完整代碼
1 import java.io.*; 2 import java.util.ArrayList; 3 import java.text.DecimalFormat; 4 5 public class CodeAnalyzer { 6 ArrayList<File> fileList; 7 File root; 8 9 public CodeAnalyzer(String pathName) { 10 root = new File(pathName); 11 fileList = new ArrayList<>(); 12 } 13 14 public void searchFiles() { 15 File[] files = root.listFiles(); 16 int length = files.length; 17 for (int i = 0; i < length; i++) { 18 if (files[i].isDirectory()) { 19 root = files[i]; 20 searchFiles(); 21 } else { 22 if (files[i].getName().endsWith(".java")) 23 fileList.add(files[i]); 24 } 25 } 26 } 27 28 public void codeAnalyze() { 29 double rowsCount = 0; 30 double commentsCount = 0; 31 double blanksCount = 0; 32 double codesCount = 0; 33 DecimalFormat df = new DecimalFormat("#.##"); 34 for (File file : fileList) { 35 try { 36 rowsCount += countRows(file); 37 blanksCount += countBlanks(file); 38 commentsCount += countComments(file); 39 codesCount = rowsCount - blanksCount - commentsCount; 40 } catch (IOException e) { 41 e.printStackTrace(); 42 } 43 } 44 //輸出結果 45 System.out.println("源程序文件總行數:" + (int) rowsCount); 46 System.out.println("代碼行數:" + (int) codesCount + ",占" + df.format(codesCount / rowsCount * 100) + "%"); 47 System.out.println("注釋行數:" + (int) commentsCount + ",占" + df.format(commentsCount / rowsCount * 100) + "%"); 48 System.out.println("空白行數:" + (int) blanksCount + ",占" + df.format(blanksCount / rowsCount * 100) + "%"); 49 } 50 51 public int countRows(File file) throws IOException { 52 BufferedReader input = new BufferedReader(new FileReader(file)); 53 int rows = 0; 54 while (input.readLine() != null) { 55 rows++; 56 } 57 return rows; 58 } 59 60 public int countBlanks(File file) throws IOException { 61 BufferedReader input = new BufferedReader(new FileReader(file)); 62 int blanks = 0; 63 String line = null; 64 while ((line = input.readLine()) != null) { 65 if (line.trim().equals("")) blanks++; 66 } 67 return blanks; 68 } 69 70 public int countComments(File file) throws IOException { 71 BufferedReader input = new BufferedReader(new FileReader(file)); 72 int comments = 0; 73 String line = null; 74 while ((line = input.readLine()) != null) { 75 line = line.trim(); 76 if (line.startsWith("//")) {//單行注釋 77 comments++; 78 } else if (line.startsWith("/*")) { //多行及文檔注釋 79 comments++; 80 while (!line.endsWith("*/")) { 81 line = input.readLine().trim(); 82 comments++; 83 } 84 } else if (line.contains("/*")) { //下行尾多行注釋 85 line = input.readLine().trim(); 86 if (line.endsWith("*/")) comments++; 87 } 88 89 } 90 return comments; 91 } 92 93 public static void main(String[] args) { 94 String pathName = "F:\\Java\\work"; 95 CodeAnalyzer analyzer = new CodeAnalyzer(pathName); 96 analyzer.searchFiles(); 97 analyzer.codeAnalyze(); 98 } 99 100 }
測試結果