软工做业——WC.exe(Java实现)

WC我的项目博客

github项目传送门:https://github.com/Lyuthia/myWC.exe.git

1、项目相关要求

       
wc.exe 是一个常见的工具,它能统计文本文件的字符数、单词数和行数。这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数、单词数和行数。前端

       
实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具有其余扩展功能,并可以快速地处理多个文件。c++

具体功能要求:

程序处理用户需求的模式为:git

wc.exe [parameter] [file_name]github

基本功能列表:

  • wc.exe -c file.c //返回文件 file.c 的字符数
  • wc.exe -w file.c //返回文件 file.c 的词的数目
  • wc.exe -l file.c //返回文件 file.c 的行数

扩展功能:

  • -s 递归处理目录下符合条件的文件。
  • -a 返回更复杂的数据(代码行 / 空行 / 注释行)。

高级功能:

  • -x 这个参数单独使用。若是命令行有这个参数,则程序会显示图形界面,用户能够经过界面选取单个文件,程序就会显示文件的字符数、行数等所有统计信息。

2、遇到的困难及解决方法

  • 困难描述:没用Java作过文件输入、命令行带参数的程序
  • 作过哪些尝试:网上搜索相关资源进行学习
  • 是否解决:是
  • 有何收获:了解并实现了相关功能

3、设计程序流程

解题思路

1.主函数:输入命令,判断是否须要经过文件夹递归查询知足条件的文件,再执行“递归查询函数”或“文件导入函数”数组

2.操做函数:循环遍历命令行,依次执行指令相应的下列统计函数函数

3.循环递归指定目录查询知足后缀条件的文件:经过File文件流依次导入该目录下的文件及文件夹进入文件数组,当该数组不为空时循环遍历数组内容,若数组内容为文件,则调用操做函数执行相应操做,若数组内容为文件夹,则迭代调用当前递归查询函数继续查询工具

4.文件导入函数:经过File文件流读取相应文件,再调用操做函数执行指令的相应函数学习

5.字符统计函数:经过readLine函数循环读取文件的每一行内容,循环遍历每一行内容中的每个字符,判断是否为符合标准的字符,是则字符数加1,不然继续判断下一个字符是否符合要求,直到结束测试

6.词数统计函数:经过readLine函数循环读取文件的每一行内容,把每一行内容以空格切割成每一个单词,再统计切割出来的单词数编码

7.行数统计函数:经过readLine函数循环读取文件的每一行内容,而后行数循环加1,直到结束

8.特殊行统计函数:经过readLine函数循环读取文件的每一行内容,判断该行是否为“空行”、“注释行”、“代码行”,是则相应变量加1,直到结束

设计实现过程

流程图

4、关键代码

项目目录:

项目目录

主函数代码:

public static void main(String[] args) throws IOException
{
    while (true) {
        // 输出面板
        System.out.println("\n----------------------3216005168 WC程序----------------------");
        System.out.println("|   |");
        System.out.println("|-c [文件路径]  返回文件字符数  |");
        System.out.println("|-w [文件路径]  返回文件词的数目|");
        System.out.println("|-l [文件路径]  返回文件行数|");
        System.out.println("|-s [文件夹路径]  搜索文件名(须为第1位) |");
        System.out.println("|-a [文件路径]  统计代码行/空行/注释行  |");
        System.out.println("|   |");
        System.out.println("-------------------------------------------------------------");

        // 获取输入指令
        System.out.println("Please enter the command:");
        Scanner command = new Scanner(System.in);
        String arr[]= command.nextLine().split("\\s");

        /* * 根据命令 执行操做 * */
        int len = arr.length;
        if(arr[0].equals("-s"))
            searchFile(arr);
        else
            operation(len,0,arr,arr[arr.length-1]);
    }
}

操做函数代码:

private static void operation(int len,int start,String[] arr,String fileName) throws IOException
{
    for(int i=start;i<len-1;i++) {
        switch (arr[i]) {
            //指定文件下字符数、单词数、行数、特殊行数
            case "-c":
            case "-w":
            case "-l":
            case "-a":
                searchByFileName(fileName,arr[i]);break;
            default:
                System.out.println("指令输入错误!");
                break;
        }
    }
}

逻辑函数代码:

1.基本功能整合

/* * 计算字符数的函数 * */
    private static void countChar(BufferedReader fileContent) throws IOException
    {
        int c = 0;//字符数
        String lineContent = null;
        while ((lineContent = fileContent.readLine()) != null)
        {
            lineContent=lineContent.trim();
            //System.out.println(lineContent);
            for(int i=0;i<lineContent.length();i++) {
                char a = lineContent.charAt(i);
                if(a!=' '&&a!='\n'&&a!='\t'&&a!=','&&a!='.'&&a!='!'&&a!=';'&&a!='=')
                    c++;
            }
        }
        System.out.println("字符数:" + c);
    }

    /* * 计算词的数目的函数 * */
    private static void countWords(BufferedReader fileContent) throws IOException
    {
        int w = 0;//词数
        String lineContent = null;
        while ((lineContent = fileContent.readLine()) != null)
        {
            lineContent=lineContent.trim();
            //System.out.println(lineContent);
            if(!lineContent.matches("^ *$"))
                w+=lineContent.replaceAll(" +"," ").split(" ").length;
        }
        System.out.println("词数:" + w);
    }

    /* * 行的数目 * */
    private static void countLines(BufferedReader fileContent) throws IOException
    {
        int l = 0;//行数
        String lineContent = null;
        while ((lineContent = fileContent.readLine()) != null)
        {
            lineContent=lineContent.trim();
            //System.out.println(lineContent);
            l++;
        }
        System.out.println("行数:" + l);
    }

    /* * 特殊行的数目:代码行数、空行数、注释行数 * */
    private static void countSpecialRows(BufferedReader fileContent) throws IOException
    {
        int blankLine = 0;//空行数
        int codeLine = 0;//代码行数
        int annotatedLine = 0;//注释行数
        Boolean comment = false;

        String lineContent = null;

        while ((lineContent = fileContent.readLine()) != null)
        {
            lineContent=lineContent.trim();
            //System.out.println(lineContent);

            if (lineContent.matches("^[\\s&&[^\\n]]*$")||lineContent.length()==1) {
                blankLine++;
            } else if (lineContent.startsWith("/*") && !lineContent.endsWith("*/")) {
                annotatedLine++;
                comment = true;
            } else if (comment.equals(true)) {
                annotatedLine++;
                if (lineContent.endsWith("*/")) {
                    comment = false;
                }
            } else if (lineContent.startsWith("//")) {
                annotatedLine++;
            } else {
                codeLine++;
            }
        }
        //System.out.println("代码行数:" + codeLine + " 空行数:" + blankLine + " 注释行数:" + annotatedLine);
        System.out.println( codeLine + " / " + blankLine + " / " + annotatedLine);
    }

    /* * 查找指定文件 * */
    private static void searchByFileName(String fileName,String command) throws IOException
    {
        try {
            File file = new File(fileName);
            if (file.isFile() && file.exists()) {
                //从文件地址中读取内容到程序中
                String encoding = "GBK";
                InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
                BufferedReader fileContent = new BufferedReader(read);

                switch (command) {
                    case "-c"://字符数
                        countChar(fileContent);break;
                    case "-w"://单词数
                        countWords(fileContent);break;
                    case "-l"://行数
                        countLines(fileContent);break;
                    case "-a"://特殊行数
                        countSpecialRows(fileContent);break;
                    default:
                        System.out.println("\n********  指令输入错误  **********");break;
                }

                read.close();
            } else {
                System.out.println("找不到指定的文件!");
            }
        } catch (Exception e) {
            System.out.println("读取文件内容操做出错");
            e.printStackTrace();
        }
    }

2.拓展功能

/* * 递归 获取 指定目录下 指定后缀 的 文件 * */
    private static void searchFile(String[] arr) throws IOException
    {
        //String fileDir = arr[arr.length-1];
        //String fileFilter = ".cpp";
        String fileDir = arr[arr.length-2];
        String fileFilter = arr[arr.length-1];

        List<File> fileList = new ArrayList<File>();
        File file = new File(fileDir);// 指定查找目录
        File[] files = file.listFiles();// 获取目录下的全部文件或文件夹
        if (files == null) {// 若是目录为空,直接退出
            return;
        }
        // 遍历files中的全部文件
        for (File f : files) {
            if (f.isFile()&&f.getName().endsWith(fileFilter)) {
                fileList.add(f);
                System.out.println(f.getName());
            } else if (f.isDirectory()) {
                arr[arr.length-2] = f.getAbsolutePath();
                System.out.println(f.getAbsolutePath());
                searchFile(arr);
            }
        }
        for (File f1 : fileList) {
            //operation(arr.length,1,arr,f1.getAbsolutePath());
            operation(arr.length-1,1,arr,f1.getAbsolutePath());
            //System.out.println(f1.getAbsolutePath());
        }
    }

5、测试运行

1.测试目录/测试文件

测试目录/测试文件

2.程序启动:

程序启动

3.基本功能:

基本功能

4.递归查询文件

递归查询文件

递归查询2

5.统计代码行、注释行、空行

特殊行数

6.代码覆盖率

覆盖率

6、PSP

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

7、项目小结

       
首先,由于本身是前端方向的,对于Java的学习也只是停留在学校教学阶段,因此在开发这个我的项目以前,从新回顾了一下Java的知识,也充分意识到本身对于Java语言的事件流的不了解,同时也学会了从0到1实现一个程序,从预估、设计、编码、开发、测试、文档等流程中锻炼本身。

        其次,在做业中使用了博客的方法来提交做业,对于一直想要搭建博客写博文却一直没有实现的本身无疑是极好的,既能培养本身写博客的习惯,又能提高本身的实践能力。

相关文章
相关标签/搜索