统计指定目录下Java源代码的总行数

来源:互联网 发布:黑魂34g内存优化 编辑:程序博客网 时间:2024/06/03 00:31

遍历指定文件夹并统计代码行数,和Java关键字频率,降序输出所有结果。

默认统计.java文件,可以自定义统计其他源码。

打算将它整合到自己做的桌面小程序中。

部分输出如下:

代码总行数:11341E:\java\以往习作\KingTetris.java--->行数:419F:\EclipseProject\Test\src\king\countcode\CountCodeLine.java--->行数:340F:\EclipseProject\记事本\src\king\notepad\view\NotepadFrame.java--->行数:332F:\EclipseProject\五子棋\src\guyuanguanli.java--->行数:298F:\EclipseProject\记事本\src\king\notepad\service\TextService.java--->行数:277F:\EclipseProject\简易绘图板\src\King\Test.java--->行数:267
---------Java代码关键字统计:----------关键字:new           出现次数:873关键字:int           出现次数:668关键字:public        出现次数:608关键字:private       出现次数:520关键字:null          出现次数:511关键字:void          出现次数:413关键字:static        出现次数:299关键字:return        出现次数:293关键字:if            出现次数:282关键字:this          出现次数:232关键字:class         出现次数:201关键字:for           出现次数:161关键字:true          出现次数:146关键字:else          出现次数:92关键字:final         出现次数:88关键字:false         出现次数:79关键字:case          出现次数:78关键字:catch         出现次数:68关键字:while         出现次数:67关键字:try           出现次数:63关键字:boolean       出现次数:60关键字:extends       出现次数:56关键字:implements    出现次数:55关键字:throws        出现次数:45关键字:break         出现次数:41关键字:char          出现次数:40关键字:super         出现次数:34关键字:byte          出现次数:32关键字:switch        出现次数:22关键字:double        出现次数:17关键字:abstract      出现次数:16关键字:do            出现次数:15关键字:protected     出现次数:13关键字:synchronized  出现次数:9关键字:long          出现次数:9关键字:finally       出现次数:8关键字:throw         出现次数:8关键字:instanceof    出现次数:7关键字:default       出现次数:6关键字:float         出现次数:2关键字:continue      出现次数:2关键字:package       出现次数:2关键字:transient     出现次数:2关键字:import        出现次数:2关键字:interface     出现次数:2关键字:native        出现次数:2关键字:volatile      出现次数:2关键字:short         出现次数:2关键字:strictfp      出现次数:1关键字:enum          出现次数:1关键字:const         出现次数:1关键字:goto          出现次数:1关键字:assert        出现次数:1

源码:

package king.countcode;import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.LinkedList;import java.util.List;import java.util.Map;import java.util.Set;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 统计指定目录下Java文件的总行数、关键字频率 * */public class CountCodeLine {    private int count = 0;    // 所有需要遍历的文件    private List<File> allFile = new LinkedList<File>();    // 所有遍历结果    private Map<String, Integer> allResult = new HashMap<String, Integer>();    // 排序后的所有遍历结果    private List<Map.Entry<String, Integer>> allSortedResult = new LinkedList<Map.Entry<String, Integer>>();    // 需要检查的文件后缀,默认添加.java    private List<String> allSuffix = new LinkedList<String>();      private static final String JAVA_SUFFIX = ".java";         //提取单词的正则表达式    private Pattern p = Pattern.compile("(?<=\\W)\\w+(?=\\W)");         //用于计数    private Keywords countKeyword = new Keywords();         public CountCodeLine(){        addSuffix(JAVA_SUFFIX);    }        public static void main(String[] args) {        CountCodeLine count = new CountCodeLine();                // 添加需要检查的文件或文件夹        count.addPath("E:\\java");        count.addPath("F:\\EclipseProject");        //        // 遍历C盘之外所有硬盘//        // 由于文件太多,全部遍历需要很久才能出结果,一般不建议//        File[] roots = File.listRoots();//        for(int i = 0; i < roots.length; i++){//            // C盘某些文件夹无权限进入,会报错,故剔除//            if (!roots[i].getAbsolutePath().toLowerCase().startsWith("c:")){//                count.addPath(roots[i].getAbsolutePath());//            }//        }                // 检查并返回统计 总行数        System.out.println("代码总行数:" + count.execute());                // 输出降序排列的总结果        for(Map.Entry<String, Integer> entry : count.getAllSortedResult()){            System.out.println(entry.getKey() + "--->行数:" + entry.getValue());        }                //输出所有Java文件中的关键字频率统计        // 如果想统计单个文件,请在上方addPath()仅输入单个文件的绝对地址        System.out.println();        System.out.println("---------Java代码关键字统计:----------");        System.out.println(count.getUsedKeywordFrequency());            }          /*     * 添加需要检查的文件或文件夹     */    public void addPath(String path){        allFile.add(new File(path));    }        /*     * 添加需要检查的后缀名     * 如果要用来统计其他后缀名的文件,请先clear()     */    public void addSuffix(String suffix){        suffix = suffix.toLowerCase(); //全转小写        if (!suffix.startsWith(".")) suffix = "." + suffix;        allSuffix.add(suffix);    }        /*     * 开始遍历     */    public int execute(){        for(File file : allFile){            checkFile(file);        }        // 排序所有结果        sortAllResult();         return getCount();    }        /*     * 获取当前count值     */    public int getCount(){        return count;    }        /*     * 返回详细的结果     * 文件名-代码行数映射的Set<Map.Entry<String, Integer>>     */    public Set<Map.Entry<String, Integer>> getAllResult(){        return allResult.entrySet();    }        /**     * 返回所有排序后的结果     */    public List<Map.Entry<String, Integer>> getAllSortedResult(){        return new LinkedList<Map.Entry<String, Integer>>(allSortedResult);    }        /**     * 返回关键字频率的统计结果     * @return     */    public String getUsedKeywordFrequency(){        return countKeyword.getUsedKeywordFrequency();    }    /*     * 清空所有内容,以便开始全新的查找     */    public void clear(){        count = 0;        allFile.clear();        allResult.clear();        allSortedResult.clear();        allSuffix.clear();            }        /*     * 遍历文件夹     */    private void checkFile(File file){        if (file.isDirectory()){            File[] files = file.listFiles();            for(File f : files){                checkFile(f);            }        } else if (checkSuffix(file)){            countLine(file);        }//        // 下面是循环方法,当递归溢出时,可改用循环//        Stack<File> stack = new Stack<File>();//        stack.push(file);//        while(!stack.isEmpty()){//            File tmp = stack.pop();           //            if (tmp.isDirectory()){//                File[] files = tmp.listFiles();//                for (File f : files){//                    stack.push(f);//                }//            } else if (checkSuffix(tmp)){//                countLine(tmp);//            }//        }    }            /**     * 检查后缀名     */    private boolean checkSuffix(File file){        String fileName = file.getName().toLowerCase();        for(String suffix : allSuffix){            if (fileName.endsWith(suffix)) return true;        }        return false;    }    /*     * 统计Java文件的行数     */    private void countLine(File file){        try (BufferedReader input = new BufferedReader(new FileReader(file))){            String str = null;            int tmpCount = 0;            while ((str = input.readLine()) != null){                // 检查这一行里的每一个单词                Matcher m = p.matcher(str);                while(m.find()){                    // 判断是否Java关键字                    countKeyword.checkWord(m.group());                }                tmpCount++;            }            count += tmpCount;            allResult.put(file.getAbsolutePath(), tmpCount); //保存到集合中        } catch (IOException e) {            e.printStackTrace();        }    }        /**     * 排序所有统计结果     * 降序     */    private void sortAllResult(){        allSortedResult.addAll(allResult.entrySet());        Collections.sort(allSortedResult, new Comparator<Map.Entry<String, Integer>>(){            @Override            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2){                int value1 = o1.getValue();                int value2 = o2.getValue();                if (value1 == value2) return 0;                return value1 > value2 ? -1 : 1;            }        });    }}//关键字集合,用于计数class Keywords {    // 所有关键字    private Map<String, Integer> keywords = new HashMap<String, Integer>();               //构造器    public Keywords(){        reset();    }        //复位清零    public void reset(){        for(Keyword k : Keyword.values()){ //从枚举类获取关键字            keywords.put(k.getKeyword(), 0);        }    }        //检测一个单词是否关键字,如果是,就让对应的关键字频数加1    public void checkWord(String word){        if (keywords.keySet().contains(word)){            keywords.put(word, keywords.get(word) + 1);        }    }        //返回统计结果    public String getUsedKeywordFrequency(){        StringBuilder result = new StringBuilder();        StringBuilder tmp = new StringBuilder();        //按频数即value值排序        //就算用TreeMap也只能对key排序,下面用自己写的比较器排序        //继承Comparator接口改改名compare方法后,TreeSet会认为compare结果为0的两个元素是同一个元素,故不用TreeSet        List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(keywords.entrySet());        Collections.sort(list, new MyMapEntryComparator());        for(Map.Entry<String, Integer> entry : list){            if (entry.getValue() != 0){                tmp.setLength(0);                tmp.append("关键字:").append(entry.getKey()).append("出现次数:").append(entry.getValue());                result.append(typeset(tmp)).append("\n");            }        }        return result.toString();    }        /**     * 将字符串排版再返回,如下输出不整齐     * 关键字:null    出现次数:1     * 关键字:implements  出现次数:1     * 控制“关键字”和“出现次数”之间的空格,     * 将来可能改变输出的汉字,故下面用正则式考虑更广泛的情况     * @param StringBuilder     * @return String     */    private String typeset(StringBuilder sb){        StringBuilder result = new StringBuilder();        int blank = 15; //不同组汉字之间的空白        int index = 0, length = 0, differ;        //找出右边不是紧邻汉字的汉字,向后数十五个空        Pattern p = Pattern.compile("(?<![一-龥])[一-龥]+(?![一-龥])");        Matcher m = p.matcher(sb);          while(m.find()){ //find()后移一位            result.append(sb.substring(index, m.start()));            if((differ = blank -(m.start() - index - length)) > 0 && m.start() != 0){                while(differ-- > 0){                    result.append(" ");                }            }                       index = m.start();            length = m.group().length();        }        //如果后面中文,则把剩下的全接上去        result.append(sb.substring(index));        return result.toString();    }        //比较用的Comparator,只在这时用到,故写成内部类    private class MyMapEntryComparator implements Comparator<Map.Entry<String, Integer>>{        @Override        public int compare(Map.Entry<String, Integer> m1, Map.Entry<String, Integer> m2){            return -(m1.getValue() - m2.getValue());        }    } }//所有关键字,枚举类,仅用于存储enum Keyword{ ABSTRACT("abstract"), ASSERT("assert"), BOOLEAN("boolean"), BREAK("break")     , BYTE("byte"), CASE("case"), CATCH("catch"), CHAR("char"), CLASS("class")     , CONST("const"), CONTINUE("continue"), DEFAULT("default"), DO("do"), DOUBLE("double")     , ELSE("else"), ENUM("enum"), EXTENDS("extends"), FALSE("false"), FINAL("final")     , FINALLY("finally"), FLOAT("float"), FOR("for"), GOTO("goto"), IF("if")     , IMPLEMENTS("implements"), IMPORT("import"), INSTANCEOF("instanceof"), INT("int")     , INTERFACE("interface"), LONG("long"), NATIVE("native"), NEW("new"), NULL("null")     , PACKAGE("package"), PRIVATE("private"), PROTECTED("protected"), PUBLIC("public")     , RETURN("return"), SHORT("short"), STATIC("static"), STRICTFP("strictfp")     , SUPER("super"), SWITCH("switch"), SYNCHRONIZED("synchronized"), THIS("this")     , THROW("throw"), THROWS("throws"), TRANSIENT("transient"), TRY("try"), TRUE("true")     , VOID("void"), VOLATILE("volatile"), WHILE("while");  private String keyword; //构造器 private Keyword(String keyword){     this.keyword = keyword; }  //获取keyword public String getKeyword() {     return keyword; }}


0 0
原创粉丝点击