• 【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

  • 相关阅读:
    判断arm立即数是否合法的小程序
    一个操作系统的实现:关于ALIGN的若干解释
    一个郁闷的C语言小问题
    test
    浮点数的比较
    一个操作系统的实现:Descriptor 3详解
    一个操作系统的实现:关于CPL、RPL、DPL
    C99可变长数组VLA详解
    SVProgressHUD 用法
    IOS CALayer 详解
  • 原文地址:https://www.cnblogs.com/heyang78/p/15754885.html
Copyright © 2020-2023  润新知