WC 代码统计 java

Posted kewenlang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WC 代码统计 java相关的知识,希望对你有一定的参考价值。

GitHub地址

项目需求

实现一个wc统计程序,可以对文本进行相关功能的统计与分析

  • 基本功能
    • -c 统计字符数
    • -w 统计文件词数
    • -l 统计行数
  • 扩展功能
    • -s 递归搜索目录下面的文件
    • -a 返回更复杂的数据(代码行 / 空行 / 注释行)

设计

主函数思路:分析命令并对-s进行预处理,得到相应的文件名字,搜索该目录下匹配的名字,根据是否需要递归进行分析,再对一条命令的每一个参数进行匹配,每次从文件读取一行字符串进行分析,再把结果打印出来。

代码

主函数

import java.io.*;
import java.util.Scanner;

public class Main {

    private static final Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        String s = null;
        while ((s = scanner.nextLine()) != null && !s.equals("exit")) {
            String[] strings = s.split(" ");

            boolean flag = false;

            for (String string : strings) {
                if (string.equals("-a")) {
                    flag = true;
                    break;
                }
            }



            File file = new File(strings[strings.length - 1]);
            String fileName = file.getName();
            if (!file.isDirectory()) {
                file = file.getParentFile();
            }
//            doFile(file,flag,strings,fileName);
            if (file != null && file.isDirectory()) {
                File[] files = file.listFiles(pathname -> {
                    if (pathname.isDirectory()) {
                        return true;
                    }
                    return isRight(pathname, fileName);
                });
                if (files != null) {
                    for (File file1 : files) {
                        doFile(file1, flag, strings, fileName);
                    }
                }
            } else {
                System.out.println("输入文件有误");

            }

        }
    }

    private static void doFile(File file, boolean flag, String[] args, String fileName) {
        if (file != null && file.isFile() && isRight(file, fileName)) {
            try (BufferedReader bf = new BufferedReader(new FileReader(file))) {
                String line;
                Result result = new Result();
                while ((line = bf.readLine()) != null) {
                    analyze(line, args, result);
                }
                result.print(file.getName());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (file != null && flag && file.isDirectory()) {
            File[] files = file.listFiles(pathname -> {
                if (fileName.equals("") || pathname.isDirectory()) {
                    return true;
                }
                return isRight(pathname, fileName);
            });
            if (files != null) {
                for (File file1 : files) {
                    doFile(file1, true, args, fileName);
                }
            }
        }
    }

    private static void analyze(String line, String[] args, Result result) {
        for (String arg : args) {
            switch (arg) {
                case "-w":
                    new WordCheck(result).check(line);
                    break;
                case "-l":
                    new LineCheck(result).check(line);
                    break;
                case "-c":
                    new CharCheck(result).check(line);
                    break;
                case "-s":
                    new StructureCheck(result).check(line);
                    break;
            }
        }
    }

    private static boolean isRight(File file, String fileName) {
        if (fileName.startsWith("*")) {
            return file.getName().endsWith(fileName.substring(fileName.lastIndexOf(".")));
        } else {
            return file.getName().equals(fileName);
        }
    }
}

字符统计

public class CharCheck implements Check {

    private final Result result;

    public CharCheck(Result result) {
        this.result = result;
    }

    @Override
    public void check(String s) {
        result.addCharLine(s.length());
    }
}

根据每一行的字符串得出长度就是字符数

统计单词

public class WordCheck implements Check {

    private final Result result;

    public WordCheck(Result result) {
        this.result = result;
    }

    @Override
    public void check(String s) {
        s = s.replaceAll("[\p{Nd}\p{Punct}\s]", " ");
        result.addWord(splitWorker(s).length);
    }


    private String[] splitWorker(final String str) {

        if (str == null) {
            return null;
        }
        final int len = str.length();
        if (len == 0) {
            return new String[]{""};
        }
        final List<String> list = new ArrayList<>();
        int sizePlus1 = 1;
        int i = 0, start = 0;
        boolean match = false;
        final char sep = " ".charAt(0);
        while (i < len) {
            if (str.charAt(i) == sep) {
                if (match) {
                    if (sizePlus1++ == -1) {
                        i = len;
                    }
                    list.add(str.substring(start, i));
                    match = false;
                }
                start = ++i;
                continue;
            }
            match = true;
            i++;
        }
        if (match) {
            list.add(str.substring(start, i));
        }
        return list.toArray(new String[list.size()]);
    }
}

使用正则表达式去除标点符号然后切割

统计行数

public class LineCheck implements Check {

    private final Result result;

    public LineCheck(Result result) {
        this.result = result;
    }

    @Override
    public void check(String s) {
        result.addLine(1);
    }

}

每一次就加1

统计复杂数据

public class StructureCheck implements Check {

    private final Result result;


    public StructureCheck(Result result) {
        this.result = result;
    }

    @Override
    public void check(String s) {
        if (s.length() == 0) {
            result.addBlankLine(1);
            return;
        }
        for (int i = 0; i < s.length(); i++) {
            if (i == s.length()-1 && s.charAt(i) == ‘ ‘) {
                result.addBlankLine(1);
                return;
            }
            if (s.charAt(i) != ‘ ‘) {
                break;
            }
        }
        boolean flag = false;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ‘/‘ && i + 1 < s.length() && s.charAt(i + 1) == ‘/‘) {
                result.addAnnotationLine(1);
                return;
            }

            if (s.charAt(i) == ‘/‘ && i + 1 < s.length() && s.charAt(i + 1) == ‘*‘) {
                flag=true;
            }
            if (s.charAt(i) == ‘*‘ && i + 1 < s.length() && s.charAt(i + 1) == ‘/‘ && flag) {
                result.addAnnotationLine(1);
                return;
            }
        }

        result.addCodeLine(1);
    }
}

统计结果

public class Result {

    private Integer line;

    private Integer word;

    private Integer blankLine;

    private Integer annotationLine;

    private Integer charLine;

    private Integer codeLine;

    private boolean b = false;

    public void print(String name) {
        if (b) {
            System.out.print("文件:" + name + ",");
        }
        if (line != null) {
            System.out.print("行数:" + line + ",");
        }
        if (word != null) {
            System.out.print("单词数:" + word + ",");
        }
        if (blankLine != null) {
            System.out.print("空白行:" + blankLine + ",");
        }
        if (annotationLine != null) {
            System.out.print("注解行:" + annotationLine + ",");
        }
        if (codeLine != null) {
            System.out.print("代码行:" + codeLine + ",");
        }
        if (charLine != null) {
            System.out.print("字符数量:" + charLine + ",");
        }
        if (b) {
            System.out.println();
        }
    }

    public void addWord(int c) {
        if (word == null) {
            word = 0;
            b = true;
        }
        word += c;
    }

    public void addLine(int c) {
        if (line == null) {
            line = 0;
            b = true;
        }
        line += c;
    }

    public void addBlankLine(int c) {
        if (blankLine == null) {
            blankLine = 0;
            b = true;
        }
        blankLine += c;
    }

    public void addAnnotationLine(int c) {
        if (annotationLine == null) {
            annotationLine = 0;
            b = true;
        }
        annotationLine += c;
    }

    public void addCharLine(int c) {
        if (charLine == null) {
            charLine = 0;
            b = true;
        }
        charLine += c;
    }

    public void addCodeLine(int c) {
        if (codeLine == null) {
            codeLine = 0;
            b = true;
        }
        codeLine += c;
    }
}

测试

在控制台下面运行代码

-a -s -l -c -w d://*.xml ,全面测试,查找d盘下面所有的xml

部分结果

文件:SoftUpdateExCache.xml,行数:409,单词数:1054,空白行:1,注解行:22,代码行:386,字符数量:12603,
文件:starttips.xml,行数:87,单词数:252,代码行:87,字符数量:2715,
文件:TestStubConfig.xml,行数:10,单词数:37,代码行:10,字符数量:405,
文件:TSBlueScreenbak.xml,行数:1619,单词数:6794,空白行:12,代码行:1607,字符数量:58010,
文件:QMExpVul.xml,行数:1305,单词数:50073,注解行:1301,代码行:4,字符数量:346076,
文件:AdFilterConfigFile.xml,行数:99,单词数:359,注解行:9,代码行:90,字符数量:4335,
文件:tsadlibblackac.xml,行数:25,单词数:115,代码行:25,字符数量:948,
文件:tsadlibcss.xml,行数:2,单词数:61707,注解行:1,代码行:1,字符数量:419166,
文件:tsadlibcssac.xml,行数:2,单词数:147879,注解行:1,代码行:1,字符数量:988044,
文件:tsadlibcssbd.xml,行数:3,单词数:1427,代码行:3,字符数量:9210,
文件:tsadlibexcept.xml,行数:2,单词数:2523,注解行:1,代码行:1,字符数量:17187,
文件:tsadlibexceptac.xml,行数:2,单词数:3606,注解行:1,代码行:1,字符数量:25367,
文件:tsadlibfloat.xml,行数:2,单词数:64683,注解行:1,代码行:1,字符数量:434538,
文件:tsadlibforce.xml,行数:55,单词数:222,注解行:6,代码行:49,字符数量:1784,
文件:tsadlibpower.xml,行数:7735,单词数:37795,注解行:902,代码行:6833,字符数量:294565,
文件:tsadlibpw.xml,行数:3,单词数:39849,注解行:2,代码行:1,字符数量:314979,
文件:tsadlibwhite.xml,行数:2,单词数:5712,代码行:2,字符数量:29556,
文件:tsadlibwhiteac.xml,行数:2,单词数:385,代码行:2,字符数量:2234,
文件:DebugModeConfigV2.xml,行数:131,单词数:2340,代码行:131,字符数量:14356,
文件:DeviceDesc.xml,行数:23,单词数:506,代码行:23,字符数量:3094,
文件:jwlxtzqn.xml,行数:10,单词数:211,代码行:10,字符数量:1296,
文件:jwlxtzqnui.xml,行数:10,单词数:97,代码行:10,字符数量:593,
文件:UnReDevice.xml,行数:96,单词数:1533,代码行:96,字符数量:9637,
文件:AppMarketPluginCtrl.xml,行数:11,单词数:109,注解行:2,代码行:9,字符数量:845,
文件:DeepSpeedupCtrl.xml,行数:11,单词数:75,注解行:1,代码行:10,字符数量:617,
文件:DeepSpeedupSrcCtrl.xml,行数:11,单词数:67,注解行:1,代码行:10,字符数量:628,
文件:DesktopMgrPluginCtrl.xml,行数:11,单词数:110,注解行:2,代码行:9,字符数量:807,
文件:DocManagerPluginCtrl.xml,行数:11,单词数:111,注解行:2,代码行:9,字符数量:821,
文件:DownloaderMgrUICtrl.xml,行数:11,单词数:74,注解行:1,代码行:10,字符数量:597,
文件:FileSmashCtrl.xml,行数:17,单词数:141,注解行:2,代码行:15,字符数量:1136,
文件:FileUnlockerCtrl.xml,行数:15,单词数:136,注解行:2,代码行:13,字符数量:1094,
文件:GameLobbyPluginCtrl.xml,行数:11,单词数:113,注解行:2,代码行:9,字符数量:874,
文件:HWPluginCtrl.xml,行数:25,单词数:189,注解行:2,代码行:23,字符数量:1626,
文件:IEStartPageCtrl.xml,行数:11,单词数:71,注解行:1,代码行:10,字符数量:569,
文件:iToolsPluginCtrl.xml,行数:11,单词数:103,注解行:2,代码行:9,字符数量:777,

再特指定的一个文件测试

-a -s -w -c- l d://123.txt

内容:

public static void main(String[] args) {
       //
    
        String s = null;
        while ((s = scanner.nextLine()) != null && !s.equals("exit")) {
            String[] strings = s.split(" ");

            boolean flag = false;

            for (String string : strings) {
                if (string.equals("-a")) {
                    flag = true;
                    break;
                }
            }

        }
    }

运行结果:

文件:123.txt,单词数:38,空白行:3,注解行:1,代码行:14,

PSP

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 40 50
· Estimate · 估计这个任务需要多少时间 40 50
Development 开发 810 860
· Analysis · 需求分析 (包括学习新技术) 120 130
· Design Spec · 生成设计文档 80 90
· Design Review · 设计复审 (和同事审核设计文档) 50 60
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 30 40
· Design · 具体设计 150 155
· Coding · 具体编码 220 225
· Code Review · 代码复审 40 40
· Test · 测试(自我测试,修改代码,提交修改) 120 120
Reporting 报告 110 150
· Test Report · 测试报告 40 60
· Size Measurement · 计算工作量 30 40
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 40 50
合计 960 1060

















以上是关于WC 代码统计 java的主要内容,如果未能解决你的问题,请参考以下文章

软件工程实践项目-WC(Java实现)

个人项目:实现wc.exe(Java)

个人小项目——Java实现WC功能

Linux下统计代码行数

统计Java项目的代码行数

java实现wc.exe的基本功能