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 }
测试结果