我需要统计今年我写了多少行代码。
要实现这个需求,需要一个前提,代码中一定要有某种标识,来标识这段代码是我写的。这个标识是存在的。我写的方法都加了注释,注释上都有“@Author .Mark”和“@Date”关键字,通过这两个关键字,我可以定位到我在2018年新增的方法。(这里还不能统计一个十分准确的数字,其中包含几方面的原因,其一,这里只能统计新增的方法,不能统计全局属性,enum类;其二,还有一些代码是在维护已经存在的代码,包括我自己写的和别人写的。但是这个统计也基本上可以实现我的需求了。)
先贴一下我写的一个类,方便阅读统计代码的时候有的放矢
package com.dhcc.mhealth.internalapi.msg;
import static com.dhcc.mhealth.common.util.list.ListUtil.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import com.dhcc.mhealth.service.internalapi.msg.MsgApiService;
/**
* @Description 消息相关项目内部类
* @Author .Mark
* @Date 2018年12月5日
*/
@Component
public class MsgInternalApi {
@Resource
private MsgApiService msgApiService;
/**
* @Description 查询csmMsg信息
* @Author .Mark
* @Date 2018年12月5日
*/
public Map<String, Object> getCsmMsgInfo(String fromUserId, String toUserId) {
Map<String, Object> result = new HashMap<>();
List<Map<String, Object>> csmMsgs = msgApiService.listCsmMsg(fromUserId, toUserId);
if (notNAE(csmMsgs)) {
result = csmMsgs.get(0);
}
return result;
}
}
第一步要做的事,是统计单个文件代码行数,代码如下:
/**
* @Description 统计文件内代码行数
* @Author .Mark
* @Date 2019年2月1日
*/
private int countLinesOfCode(File file) {
int sum = 0;
try {
// 1.读取文件
if (file.isFile() && file.exists()) {
FileInputStream fileInputStream = new FileInputStream(file);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
// 2.文件按行存入ArrayList
List<String> fileList = new ArrayList<>();
String lineTxt = null;
while ((lineTxt = bufferedReader.readLine()) != null) {
fileList.add(lineTxt);
}
// 3.统计代码量
int startNum = 0;
int endNum = 0;
if (fileList != null && !fileList.isEmpty()) {
// 3.1.找到类代码开始行
int classCodeStartNum = 0;
for (int i = 0; i < fileList.size(); i++) {
String thisLine = fileList.get(i);
if (thisLine != null && thisLine.contains("{")) {
classCodeStartNum = i;
break;
}
}
for (int i = classCodeStartNum + 1; i < fileList.size(); i++) {
// 3.2.找到注释,确定这个方法是我写的
String thisLine = fileList.get(i).replace(" ", "");
boolean myMethod = (thisLine != null) && thisLine.contains(AUTHOR_MARK) && fileList.get(i + 1).replace(" ", "").contains(DATE_2018);
if (myMethod) {
// 3.3.根据“{”确定注释下的方法开始,方法开始行作为startNum
for (int j = i + 2; j < fileList.size(); j++) {
thisLine = fileList.get(j);
if (thisLine != null && thisLine.contains("{")) {
startNum = j;
break;
}
}
// 3.4.根据“}”确定方法结束,方法结束行作为endNum
int numOfOpenBrace = 1;
for (int j = startNum + 1; j < fileList.size(); j++) {
thisLine = fileList.get(j);
if (thisLine != null && thisLine.contains("{")) {
numOfOpenBrace++;
}
if (thisLine != null && thisLine.contains("}")) {
numOfOpenBrace--;
}
if (numOfOpenBrace == 0) {
endNum = j;
i = j + 1;
sum += (endNum - startNum + 1);
break;
}
}
}
}
}
fileInputStream.close();
inputStreamReader.close();
bufferedReader.close();
} else {
System.err.println("file not available");
}
} catch (Exception e) {
e.printStackTrace();
}
return sum;
}
代码主要逻辑如下:
- 1.找到关键字,确定这个方法是我写的
- 2.根据“{”确定注释下的方法开始,方法开始行作为startNum
- 3.根据“}”确定方法结束,方法结束行作为endNum
- 4.(endNum - startNum + 1) 得到该方法行数
第二步是拿到项目下所有的Java文件,代码如下:
/**
* @Description 拿到目录下所有Java文件
* @Author .Mark
* @Date 2019年2月1日
*/
private List<File> getAllFile(String path) {
// 1.读入文件夹
File file = new File(path);
// 2.拿到文件夹的子目录
File[] files = file.listFiles();
// 3.遍历这个子目录,判断是否是Java文件
if (files != null && files.length != 0) {
for (File tmp : files) {
// 3.1.是Java文件,则这个文件是我需要的
if (tmp.isFile() && tmp.getPath().endsWith(".java")) {
allFiles.add(tmp);
}
// 3.2.如果是目录,递归调用2到4
else if (tmp.isDirectory()) {
getAllFile(tmp.getPath());
}
}
}
return allFiles;
}
这个方法采用了递归调用的方式,遍历每个目录及子目录;这个方法是可复用在其他需要遍历整个文件夹的地方的。
第三步是通过调用以上两个方法统计出今年增加的代码行数,代码如下:
package com.dhcc.mhealth.common.util.count.code.quantity;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* @Description 统计代码量
* @Author .Mark
* @Date 2019年2月1日
*/
public class CountCodeQuantity {
/**
* 作者是.Mark
*/
private static final String AUTHOR_MARK = "@Author.Mark";
/**
* 方法是2018年写的
*/
private static final String DATE_2018 = "@Date2018";
/**
* 统计所有Java文件的基础文件夹
*/
private static final String ROOT_PACKAGE = "D:\\development\\workspace\\jklApi";
/**
* 基础文件夹下所有Java文件
*/
private List<File> allFiles = new ArrayList<>();
public static void main(String[] args){
int sum = 0;
CountCodeQuantity countCodeQuantity = new CountCodeQuantity();
// 1.拿到目录下所有Java文件
List<File> allFiles = countCodeQuantity.getAllFile(ROOT_PACKAGE);
if (allFiles != null && allFiles.size() != 0) {
for (File file : allFiles) {
// 2.统计单个Java文件内代码行数
int linesOfCode = countCodeQuantity.countLinesOfCode(file);
// 3.单个文件内代码行数加到总代码行数上
sum += linesOfCode;
}
}
System.err.println("总代码行数:" + sum);
}
}