zoukankan      html  css  js  c++  java
  • 【Java】一个类搞定代码行统计

    数月前在一个项目,听见PM说那谁谁用某某工具把代码行统计一下给我,当时作为旁观者的我听了想,这个自己写个类不好吗?

    昨天正好一项目也要统计代码行,于是便写了这么一个类:

    package test;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.TreeMap;
    
    /**
     * 代码行计数器
     * 一个类实现工程中各种代码行统计
     * @author ufo
     * 2022年1月1日
     */
    public class CodelineFigurer {
        // 要统计的工程根目录
        private String root;
        
        // 要排除的路径
        private List<String> exclusivePaths;
        
        // 要排除的扩展名
        private List<String> exclusiveExts;
        
        // 存储代码文件路径
        private List<String> codeFiles;
        
        /**
         * 构造函数
         * @param root
         */
        public CodelineFigurer(String root) {
            this.root=root;
        }
        
        /**
         * 添加排除路径
         * @param path
         * @return
         */
        public CodelineFigurer addExclusion(String path) {
            if(exclusivePaths==null) {
                exclusivePaths=new ArrayList<>();
            }
            
            exclusivePaths.add(path);
            return this;
        }
        
        /**
         * 添加排除扩展名
         * @param ext
         */
        public void addExclusiveExt(String ext) {
            if(exclusiveExts==null) {
                exclusiveExts=new ArrayList<>();
            }
            
            exclusiveExts.add(ext);
        }
        
        /**
         * 开始遍历目录,分类汇总,打印报告
         */
        public void start() {
            codeFiles=new ArrayList<>();
            
            tranversal(new File(this.root));
            
            figure();
        }
        
        /**
         * 递归遍历目录
         * @param folder
         */
        private void tranversal(File folder) {
            // 遇到排除路径则退出
            String path=folder.getAbsolutePath();
            for(String exclusivePath:exclusivePaths) {
                if(path.startsWith(exclusivePath)) {
                    return;
                }
            }
            
            File[] files=folder.listFiles();
            
            for(File f:files) {
                if(f.isFile()) {
                    // 遇到排除的扩展名即退出
                    for(String ext:exclusiveExts) {
                        if(f.getAbsolutePath().endsWith(ext)) {
                            return;
                        }
                    }
                    
                    codeFiles.add(f.getAbsolutePath());
                }else if(f.isDirectory()) {
                    tranversal(f);
                }
            }
        }
        
        /**
         * 分类汇总代码行
         */
        private void figure() {
            Map<String,Integer> map=new TreeMap<>();
            
            for(String path:codeFiles) {
                int cnt=countCodeLine(path);
                
                if(cnt>0) {
                    String ext=extractExt(path);
                    
                    if(map.containsKey(ext)) {
                        int sum=map.get(ext);
                        sum+=cnt;
                        map.put(ext, sum);
                    }else {
                        map.put(ext, cnt);
                    }
                }
            }
            
            StringBuilder sb=new StringBuilder();
            String line=null;
            int total=0;
            for(Entry<String,Integer> entry:map.entrySet()) {
                int cnt=entry.getValue();
                line=String.format("%-10s:%10d\n", entry.getKey(),cnt);
                sb.append(line);
                total+=cnt;
            }
            
            line=String.format("%-10s:%10d\n", "total",total);
            sb.append(line);
            
            System.out.println(sb.toString());
        }
        
        /**
         * 从文件路径中抽取扩展名
         * @param filepath
         * @return
         */
        private String extractExt(String filepath) {
            filepath=filepath.toLowerCase();
            
            int dotIdx=filepath.lastIndexOf(".");
            if(dotIdx>0) {
                return filepath.substring(dotIdx+1);
            }
            
            return null;
        }
        
        /**
         * 数一个文本文件中有多少代码行
         * 代码行即有文字的行 注释行被认定是代码行的一部分
         * @param filepath
         * @return
         */
        private int countCodeLine(String filepath) {
            try {
                int cnt=0;
                
                BufferedReader reader=new BufferedReader(new InputStreamReader(new FileInputStream(new File(filepath))));
                
                String line=null;
                
                while((line=reader.readLine())!=null) {
                    if(line.trim().length()>0) {
                        cnt++;
                    }
                }
                
                return cnt;
            }catch(Exception ex) {
                ex.printStackTrace();
                return 0;
            }
        }
        
        // 启动
        public static void main(String[] args) {
            CodelineFigurer cf=new CodelineFigurer("C:\\hy\\prog\\mediaCool\\src");
            cf.addExclusion("C:\\hy\\prog\\mediaCool\\src\\main\\resources\\static\\lib").addExclusion("C:\\hy\\prog\\mediaCool\\src\\main\\resources\\static\\stylesheets");
            cf.addExclusion("C:\\hy\\prog\\mediaCool\\src\\main\\resources\\static\\images");
            cf.addExclusiveExt("gitignore");
            cf.start();
        }
    }

    输出:

    html      :      3066
    java      :      1011
    sql       :        50
    xml       :        58
    yml       :        44
    total     :      4229

    看吧,的确是一个类能搞定!作为程序员,能自己动手编码搞定的事情当然不会求助于工具,您说对吗?

    END

  • 相关阅读:
    LeetCode 345. Reverse Vowels of a String 题解
    LeetCode 344. Reverse String 题解
    LeetCode 27. Remove Element 题解
    LeetCode 61. Rotate List 题解
    LeetCode 19.Remove Nth Node From End of List 题解
    Android耗电量
    Android 使用adb查看和修改电池信息
    Android AOP AspectJ 插桩
    Flask相关用法
    Monkey日志信息的11种Event percentage
  • 原文地址:https://www.cnblogs.com/heyang78/p/15754885.html
Copyright © 2011-2022 走看看