一個簡單的代碼計數器的實現


source counter

這是一個簡單的懶人源碼統計工具.目前實現的功能相對來說比較簡單,只是對注釋,空白行和代碼做了簡單的區分.
之后還想加入一些更精確的統計方式.不過,暫時還沒想好要怎么弄.(捂臉,逃…)

目前的源碼已經上傳至github,下載的話請點擊這里. sourceCounter

下面簡單介紹一下實現

查找一個目錄及其子目錄下的文件

這個很簡單,一個遞歸就搞定了. 第一個方法getAllFiles() 是查找一個目錄及其子目錄下的所有文件.
第二個方法是根據指定的文件名查找文件.文件名在這里都是使用字符串來記錄的. 所以,完全可以使用正則表達式來匹配所有后綴為*.java的文件. 當然,也可以匹配其他后綴的文件.

1.public class FileUtils {
2.
3. private static List<String> fileList = new ArrayList<String>();
4.
5.
6. /**
7. * to get all files in a directory and it's child dir
8. * @param root
9. * @return
10. */

11. private static void getAllFiles(String root){
12. File[] files = new File(root).listFiles();
13. for(File eachFile : files){
14. if(eachFile.isDirectory()){
15. FileUtils.getAllFiles(eachFile.getAbsolutePath());
16. // fileList.add(eachFile.getAbsolutePath());
17. }else {
18. fileList.add(eachFile.getAbsolutePath());
19. }
20.
21. }
22. }
23.
24. public static List<String> findFiles(String root,String type){
25. getAllFiles(root);
26. List<String> sourceFile =new ArrayList<String>();
27. Pattern pattern = Pattern.compile("\\."+type+"$");
28. for(String eachFile:fileList){
29. Matcher matcher = pattern.matcher(eachFile);
30. if(matcher.find()){
31. sourceFile.add(eachFile);
32. }
33.
34. }
35. return sourceFile;
36. }
37.}

區分源碼中的代碼行,空行和注釋行

這里核心就是一個正則表達式的匹配. 需要注意的兩個地方是:

  • 轉義字符: 比如,對於”//”這個來說, 它對於java的正則引擎而言它是保留關鍵字,是需要轉義的. 轉義的方式很簡單,按照正常的劇本應該是在字符前加上”\”就可以了.(話說這是正斜杠還是反斜杠啊,分不清…),所以”//”的轉義應該是”\/\/”. 但是!!!but!!! java里對於”\” 也特么被保留了. 所以如果想表示”//” 應該寫成”\/\/” . 或者使用unicode編碼來進行轉義. 我翻遍我當年的筆記,關於正則表達式中的轉義字符全寫的是”\”而不是”\”… 自己把自己坑了…
  • 關於空行:java源碼里的空行大部分都是由於排版需要敲出來的空格,換行符和制表符.(貌似空行也就這三類吧…). 所以匹配空行的正則表達式是\\s*|\t|\r|\n"
1.public class CounterUtils {
2. /**
3. * match each line in a source file to distinguish source code and comments
4. * @param sourceFile
5. * @return
6. * @throws IOException
7. */

8. public static Map<String, Integer> sourceFileCounter(File sourceFile) throws IOException{
9. int sourceCount =0;
10. int commentCount=0;
11. Map<String, Integer> counterMap = new HashMap<String, Integer>();
12.
13. FileReader fr = new FileReader(sourceFile);
14. BufferedReader br = new BufferedReader(fr);
15.
16. Pattern singleCommentPattern = Pattern.compile("\\/\\/"); //single line comments
17. Pattern blockCommentPattern1 = Pattern.compile("\\/\\*");//block comments
18. Pattern blockCommentPattern2 = Pattern.compile("\\*");//block comments
19. Pattern blankPattern = Pattern.compile("\\s*|\t|\r|\n");//blank line
20.
21. String eachLine = null;
22.
23. while((eachLine=br.readLine())!=null){
24. Matcher singleCommentMatcher = singleCommentPattern.matcher(eachLine);
25. Matcher blockComment1Matcher = blockCommentPattern1.matcher(eachLine);
26. Matcher blockComment2Matcher = blockCommentPattern2.matcher(eachLine);
27. Matcher blankMatcher = blankPattern.matcher(eachLine);
28. if(singleCommentMatcher.find()||blockComment1Matcher.find()||blockComment2Matcher.find()){
29. commentCount++;
30. }else if (blankMatcher.matches()) {
31. continue;
32. }else {
33. sourceCount++;
34. }
35. }
36.
37. counterMap.put("sourceCount", sourceCount);
38. counterMap.put("commentCount",commentCount);
39.
40. return counterMap;
41. }
42.}

操作excel的第三方jar包

由於以前寫的工具,絕大部分都是處理文本數據用的. 所以我對正則表達式和excel,csv文件情有獨鍾. 按照我的設想是,程序運行之后,將統計數據記錄到excel中,方便我日后畫圖. 所以這里使用了一個第三方的jar包來操作保存結果的excel.

這里使用的是jexcelapi. 還挺方便的,api一看就懂.

可能是我的腦回路不正常,按照我的理解,這個jar包並沒有提供直接修改一個excel的方法. 因為它所有workbook相關的方法都叫createXXX. 但是后來看到一個例子,可以先get到你需要修改的excel文件,然后再create的時候作為copy傳進去. 先在讀取原文件,然后操作,然后覆蓋回寫. 反正也達到了修改的目的.

1.public class ExcelUtils {
2. public static void writeToResultFile(int sourcCount,int commentsCount,String path)
3. throws IOException, BiffException, RowsExceededException, WriteException
{
4. String sourceCount = Integer.toString(sourcCount);
5. String commentCount = Integer.toString(commentsCount);
6.
7. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
8. String date=sdf.format(new Date());
9.
10.
11. File resultFile = new File(path);
12. //get source workbook
13. Workbook book = Workbook.getWorkbook(resultFile);
14. //create a new workbook using source workbook as a copy
15. WritableWorkbook wb = Workbook.createWorkbook(resultFile, book);
16. WritableSheet sheet = wb.getSheet(0);
17. int rows = sheet.getRows();
18.
19. if(rows==0){
20. //add a cell
21. Label dateLabel = new Label(0,0,"date");
22. Label srcLabel = new Label(1,0,"srcCount");
23. Label cmtLabel = new Label(2,0,"cmtCount");
24.
25. sheet.addCell(cmtLabel);
26. sheet.addCell(srcLabel);
27. sheet.addCell(dateLabel);
28. rows++;
29. }
30. Label dateLabel = new Label(0,rows,date);
31. Label srcCount = new Label(1,rows,sourceCount);
32. Label cmtCount = new Label(2,rows,commentCount);
33.
34. sheet.addCell(dateLabel);
35. sheet.addCell(srcCount);
36. sheet.addCell(cmtCount);
37.
38. wb.write();
39. wb.close();
40.
41. }
42.}

統計一個目錄下的所有指定類型源文件

好了,文件查找的方法有了,源碼內容識別的方法有了,回寫記錄的方法也有了. 我們最后要做的就是把這些玩意兒整合起來,讓它可以工作.

我平時使用myeclipse和eclipse,所以源碼基本上都在一個目錄下面, 而且,到目前為止,我只關心java代碼的數量(因為我只會這玩意兒…) 但是顯然,這個玩意兒除了java代碼還可以查找其他類型的源碼. 所以我不想把它寫的太死板,留了一個配置文件出來. 需要的時候可以直接修改配置文件就可以了.

1.path=C\:\\Users\\thecatcher\\Documents\\workbench
2.fileType=java
3.resultPath=C\:\\Users\\thecatcher\\Documents\\codeCounter.xls

主方法很簡單,就是把這些玩意兒穿起來.

1.public class SourceCounter {
2. private static String path;
3. private static String fileType;
4. private static String resultFile;
5. private static Map<String, Integer> sourceCounterMap = new HashMap<String, Integer>();
6.
7. public static void main(String[] args) throws FileNotFoundException,
8. IOException, RowsExceededException, BiffException, WriteException
{
9. //get configuration info form config file
10. Properties prop = new Properties();
11. prop.load(new FileInputStream(
12. new File(
13. "C:\\Users\\thecatcher\\Documents\\workbench\\SourceCounter\\src\\config.properties")));
14.
15. path = prop.getProperty("path");
16. fileType = prop.getProperty("fileType");
17. resultFile = prop.getProperty("resultPath");
18.
19. List<String> sourceFileList = FileUtils.findFiles(path, fileType);
20.
21. //initialize data map
22. sourceCounterMap.put("sourceCount", 0);
23. sourceCounterMap.put("commentCount", 0);
24.
25. for (String eachFile : sourceFileList) {
26. Map<String, Integer> eachFileMap = CounterUtils
27. .sourceFileCounter(new File(eachFile));
28. sumCounter(eachFileMap, sourceCounterMap, "sourceCount");
29. sumCounter(eachFileMap, sourceCounterMap, "commentCount");
30. }
31. // System.out.println(sourceCounterMap.get("sourceCount"));
32. // System.out.println(sourceCounterMap.get("commentCount"));
33. // System.out.println(sourceFileList.size());
34. ExcelUtils.writeToResultFile(sourceCounterMap.get("sourceCount"),
35. sourceCounterMap.get("commentCount"), resultFile);
36.
37. System.out.println("---------------------");
38. System.out.println("done!");
39. System.out.println("---------------------");
40. System.out.println("source Code: "+sourceCounterMap.get("sourceCount"));
41. System.out.println("commentCount: "+sourceCounterMap.get("commentCount"));
42. }
43.
44. private static void sumCounter(Map<String, Integer> srcMap,
45. Map<String, Integer> destMap, String key)
{
46. int srcCounter = srcMap.get(key);
47. int destCounter = destMap.get(key);
48. int sum = srcCounter + destCounter;
49.
50. destMap.put(key, sum);
51. }
52.
53.}

將工程打包成可執行的jar包

表示這個還真是用百度google到的內容. 之前一直寫寫寫,卻沒有想過怎么打包工程…
首先說一件很羞恥的事情…我用的破解版的myeclipse10…為啥用這個,因為最初啟蒙入門的時候看別人的教學視頻,人家用的就是這個,所以一直就用下來了. 我想我會改邪歸正…不再用盜版軟件的…

步驟很簡單,

在項目上右鍵,export,然后選擇runnable JAR file

.1488791138111

然后,第一個選擇你的程序主類入口,第二個選擇導出位置

 .1488791179440
下面那個是選擇如何處理添加的第三方類庫的.不重要,我就保持了默認的第一個.

然后點finish就可以了.

重點來了

這么個小玩意兒很好寫,但是寫完之后怎么用呢? 我最初的想法是能每天定時執行,然后等我足夠牛X的時候,拿出來畫個圖看看自己代碼量增長的曲線,順帶緬懷一下逝去的青春(捂臉,再逃…)

每天手動點一次,這個方法太low了. 畢竟,我是個連呼吸都覺得略累的懶宅死胖子. 考慮到我嚴重的失眠情況以及幾乎趨近於0的夜生活,我的電腦,幾乎每天凌晨00:00都是處於運行狀態的. 所以我定了一個定時任務. 讓這個玩意兒每天零點都執行一下.

首先寫一個批處理,很簡單,一句話:

1.@echo off
2.java -jar C:\Users\thecatcher\Documents\002.tools\sourceCounter\counter.jar
3.pause

然后,開始菜單里找到任務計划程序–操作–創建基本任務

.1488791586829

名稱描述隨便寫了.

.1488791643219

然后下一步,觸發器,看你要執行的頻率和條件.

然后操作,這里我們選啟動程序

.1488791717333

然后這里我們找到剛才寫的那個批處理文件

.1488791735456

然后下一步,完成就好了.

要查看剛才新建的計划任務,
在左側區域選擇任務計划程序庫就可以看到所有計划任務的執行情況了.

.1488791808881

我剛剛突然想到一個問題…貌似可以直接根據文件的創建日期或者最后修改日期來統計,這樣的話只需要在我想看的時候,執行一下就可以了…我是不是白忙活了…



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM