zoukankan      html  css  js  c++  java
  • Word Count作业

    Java语言实现初步Word Count

    1.GitHub项目网址:

    项目语言:Java;编译运行平台:IntelliJ IDEA;Github网址:https://github.com/DuoRouLongShu/WordCount

    2.个人PSP

    PSP2.1

    Personal Software Process Stages

    预估耗时(分钟)

    实际耗时(分钟) 

     Planning

     计划

     30

    ·Estimate 

    ·估计这个任务需要多少时间 

    30 

     Development

    开发 

    1600

     ·Analysis

    ·需求分析 (包括学习新技术)

     120

     ·Design Spec

     ·生成设计文档

     20

     ·Design Review

     ·设计复审(和同事审核设计文档)

    50

     ·Coding Standard

      ·代码规范(为目前的开发指定合适的规范)

     30

      ·Design

     ·具体设计 

    80

      ·Coding

     ·具体编码 

    150

     ·Code Review 

     ·代码复审 

     30

     ·Test

     ·测试(自我测试,修改代码,提交修改) 

    120

     

    Reporting 

     报告 

     60

     ·Test Report 

     ·测试报告 

     75

     ·Size Measurement  

     ·计算工作量 

    10 

     ·Postmortem & Process Improvement Plan

     事后总结,并提出过程改进计划

     15

    Total

    合计 

    2765


    3.题目介绍与解题思路

    3.1题目:

    实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。 具体功能要求: 程序处理用户需求的模式为:wc.exe [parameter] [file_name]

    基本功能列表:

    wc.exe -c file.c //返回文件 file.c 的字符数

    wc.exe -w file.c //返回文件 file.c 的词的数目

    wc.exe -l file.c //返回文件 file.c 的行数

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

    空行:本行全部是空格或格式控制字符,如果包括代码,则只有不超过一个可显示的字符,例如“{”。

    代码行:本行包括多于一个字符的代码。

    注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释:

    } //注释 在这种情况下,这一行属于注释行。

    高级功能:

    -x 参数。这个参数单独使用。如果命令行有这个参数,则程序会显示图形界面,用户可以通过界面选取单个文件,程序就会显示文件的字符数、行数等全部统计信息。

    需求举例:   wc.exe -s -a .c

    返回当前目录及子目录中所有.c 文件的代码行数、空行数、注释行数。

    3.2解题思路

    3.2.1需求分析

    1. 简单思路

      • 拿到题目我想到用Java实现的话,应该分成两大模块,一是各个统计功能的代码实现,二是怎样获取到所需文件。初步想法是文件的获取录入采用文件流的思想,逐步获取到所需文件;然后将获取到的文件里面的内容按照要求的功能调用相关的方法

      • 这样的话应该先把各个统计功能先实现,因为这是整个程序的核心。应该可以用到上课学的,单元测试,单元开发,这样就不用一个点设计错误全盘错误

    2. 找资料

      这是最头痛的,因为很多很多自己都还没学过,直接上手这样一个Java项目着实吓到我了

      • 查了正则表达式,因为觉得它好像是能具体字符出什么是什么,会对统计功能实现起到极方便的作用

      • 查了单元测试,基于idea平台该如何进行,确实会帮到你开发,具体的junit链接都放在CSDN收藏夹。

      • 查了如何将Java程序转成exe,因为看着需求确实不明白该怎样输入程序,以及自己的知识盲区图形化GUI界面这些

    3.2.1程序框架

    4.设计实现过程

    4.1项目总体布局

    • WordCountDemo是入口参数类,用以处理入口参数判断以及选择具体统计功能的主类

    • TooltoCount是统计工具类,用以调用具体的文件流方法,以及统计功能方法

    4.2具体类与具体函数与其之间的调用

    • WordCountDemo类里面的函数:public static void main(String[] args)和public String judge(String[] args)

    • TooltoCount类里面的函数:

      public String countCharacters(Set<String> file_paths)
      public String countWords(Set<String> file_paths)
      public String countLines(Set<String> file_paths)
      public String countCodeLines(Set<String> file_paths)
      public String countEmptyLines(Set<String> file_paths)
      public String countNoteLines(Set<String> file_paths)
      public Set<String> FilePaths(Set<String> names)
      public static Set<String> DirectoryFilePaths(Filefile)
    • 它们之间的关系

    5.代码说明

    /**
    *统计字符数
    *输入参数为文件路径
    */
    public String countCharacters(Set<String> file_paths) {
        int sum = 0,bytes = 0;
        byte[] t = new byte[30*2048];//存储字符数组
        String count_result = "";
        int length = t.length;//新建length避免循环调用t.length
        FileInputStream in = null;
        try {
            for (String file_path : file_paths) {
                in = new FileInputStream(file_path);
                while ((bytes = in.read(t,0,length))!=-1) {
                    sum+=bytes;//统计字符数
                }
                count_result += file_path + "-字符数:" + sum ;//存储输出的结果
                sum = 0;
            }
            //如果输入有误
        } catch (FileNotFoundException e) {//抛出程序异常,退出程序
            System.exit(0);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return count_result;
    }
    ​
    /**
    *统计单词数
    *输入参数为文件路径
    */
    public String countWords(Set<String> paths){
            int Count = 0;
            String count_result = "";
            StringBuffer SaveString = new StringBuffer();
            String Tmp = "";
            try {
                for (String Path : paths) {
                    Tmp = SaveString.toString();//用split方法区分单词
                    Tmp = Tmp.replaceAll("[^a-zA-Z\s+]", " ");
                    Total = Tmp.split("[\s+,\.
    ]");//读取到的输入文件的数组
                    Count = Total.length;
                    count_result += Path+"-单词数:"+Count;// 字符串数组长度就是单词个数
                    SaveString.setLength(0);
                    Count = 0;
                }
            } catch (FileNotFoundException e) {
                // 检查到文件不存在,结束程序
                System.exit(0);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return count_result;
        }




    /**
    *统计代码数
    *输入参数为文件路径
    */
      public String countCodeLines(Set<String> paths) {
          FileInputStream is = null;
            InputStreamReader ist = null;
            BufferedReader br = null;
            try {
                for (String filePath :paths) {
                    is = new FileInputStream(filePath);
                    ist = new InputStreamReader(is);
                    br = new BufferedReader(ist);
                    while((tmp = br.readLine())!=null) { // 去除读取的空格
                        tmp = tmp.replace(" ", "");
                        if (!"".equals(tmp)&&!tmp.startsWith("//")&&tmp.indexOf("//")!=1) {
                            count++;// 改行不为空,则计数+1
                        }
                    }
                    // 拼接结果字符串
                    result+=filePath + "-代码行数:" + count;
                    // 重置count
                    count = 0;
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    // 关闭输入流
                    is.close();
                    ist.close();
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
            return result;
        }
    public String countLines(Set<String> filePaths) {
            int count = 0;
                // foreach循环遍历数组
                for (String filePath : filePaths) {
                    bis = new BufferedReader(isr); // 实例化缓存输入流对象
                    while (bis.readLine()!=null) {
                        count++;
                    }
                    // 结果字符
                    result += filePath+",行数:" + count;count = 0;
                }
            } catch (FileNotFoundException e) {
                // 检查到文件不存在
                // 结束程序
                System.exit(0);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    // 关闭文件字符输入流
                    in.close();
                    // 关闭字节输入流
                    isr.close();
                    // 关闭缓存输入流
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
            return result;
        }
    countLines
    public String countEmptyLines(Set<String> filePaths) {
            // 结果字符串
            String result = "";
            // 缓存变量
            String tmp = "";
            // 统计次数
            int count = 0;
            // 得到输入流
            FileInputStream is = null;
            InputStreamReader ist = null;
            BufferedReader br = null;
            try {
                for (String filePath : filePaths) {
                    is = new FileInputStream(filePath);
                    ist = new InputStreamReader(is);
                    br = new BufferedReader(ist);
                    while((tmp = br.readLine())!=null) {
                        // 改行不为空,则计数+1
                        if ("".equals(tmp)) {
                            count++;
                        }
                    }
                    // 拼接结果字符串
                    result+=filePath+ ",空行数:" + count;
                    // 重置count计数变量
                    count = 0;
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    // 关闭输入流
                    is.close();
                    ist.close();
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
            return result;
        }
    countEmptyLines
    public String countNoteLines(Set<String> filePaths) {
            // 结果字符串
            String result = "";
            // 缓存变量
            String tmp = "";
            // 统计次数
            int count = 0;
            // 得到输入流
            FileInputStream is = null;
            InputStreamReader ist = null;
            BufferedReader br = null;
            try {
                for (String filePath : filePaths) {
                    is = new FileInputStream(filePath);
                    ist = new InputStreamReader(is);
                    br = new BufferedReader(ist);
                    while((tmp = br.readLine())!=null) {
                        // 去除读取的空格,方便识别内容类型
                        tmp = tmp.replace(" ", "");
                        // 改行不为空,则计数+1
                        if (!"".equals(tmp)&&tmp.startsWith("//")||tmp.indexOf("//")==1) {
                            count++;
                        }
                    }
                    // 拼接结果字符串
                    result+=filePath + ",注释行数:" + count;
                    // 重置count计数变量
                    count = 0;
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    // 关闭输入流
                    is.close();
                    ist.close();
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
            return result;
        }
    countNoteLines
    /**
    *主函数main
    *调用程序入口参数
    */
    public static void main(String[] args) {
            String choose = null ;//判断输入变量
            //新建WordCountDemo类,用以控制函数调用
            WordCountDemo wordCountDemo = new WordCountDemo();
            Scanner scanner = new Scanner(System.in);
            System.out.println("校验是否执行如下命令行:");
            //循环输出命令行
            for (int i = 0;i < args.length;i++){
                System.out.println(args[i]);
            }
            System.out.println("输入Y确定并执行程序,输入N退出程序");
            choose = scanner.nextLine();
            if (choose.charAt(0) == 'Y') {
                wordCountDemo.judge(args);//如果命令行没错就执行判断方法
            }else {
                System.exit(0);
            }
        }        
    /**
    *judge函数,用于判断入口参数命令行,判断调用那些统计方法
    *入口参数为args
    */
    public String judge(String[] args){
            String count_result = "";
            //取得文件输入流
            paths = tooltoCount.getAllFilePaths(paths);
            for (int i = 0;i < args.length;i++){
                //循环判断输入命令是否为功能
                if(!args[i].startsWith("-") || args[i].endsWith("-s")){
                    if (args[i].startsWith("-s")){
                        paths.add(args[i+1]);//如果为-s,收集查询条件
                    }
                    paths.add(args[i]);//
                }
            }
            for (int j = 0;j < args.length;j++){
                if (args[j].startsWith("-") == true){
                    switch (args[j]){
                        case "-c":
                            //-c指令
                            count_result += tooltoCount.countCharacters(paths) + "
    ";
                            break;
                        case "-w":
                            //-w指令
                            count_result += tooltoCount.countWords(paths) + "
    ";
                            break;
                        case "-l":
                            //-l指令
                            count_result += tooltoCount.countLines(paths) + "
    ";
                            break;
                        case "-s":
                            //-s指令
                            if (!args[j+1].startsWith("-")){
                                paths = tooltoCount.getAllFilePaths(paths);
                            }
                            break;
                        case "-a":
                            //-a指令
                            count_result += tooltoCount.countCodeLines(paths) + "
    ";
                            count_result += tooltoCount.countEmptyLines(paths) + "
    ";
                            count_result += tooltoCount.countNoteLines(paths) + "
    ";
                            break;
                        case "-x":
                            //-c指令,还未实现
                            break;
                        default:
                            System.out.println("输入错误!");
                            break;
                    }
                }
            }
            System.out.println(count_result);
            return count_result;
        }

    6.测试运行

    单元测试:

    //junit单元测试
    @org.junit.Test
        public void testcountCharacters() {
            Set<String> filePaths = new HashSet<String>();
            String File1 = "E:\test.java";
            String File2 = "E:\WordCount";
            filePaths.add(File2);
            filePaths.add(File1);
            filePaths =new TooltoCount().getAllFilePaths(filePaths);
            String Result = new TooltoCount().countCharacters(filePaths);
            System.out.println(Result);
        }
    
        @org.junit.Test
        public void testcountWords() {
            Set<String> filePaths = new HashSet<String>();
            String File1 = "E:\test.java";
            String File2 = "E:\WordCount";
            String stopList = "";
            filePaths.add(File2);
            filePaths.add(File1);
            filePaths =new TooltoCount().getAllFilePaths(filePaths);
            System.out.println(new TooltoCount().countWords(filePaths));
        }
    
        @org.junit.Test
        public void testcountLines(){
            Set<String> filePaths = new HashSet<String>();
            String File1 = "E:\test.java";
            String File2 = "E:\WordCount";
            filePaths.add(File2);
            filePaths.add(File1);
            filePaths =new TooltoCount().getAllFilePaths(filePaths);
            System.out.println(new TooltoCount().countLines(filePaths));
        }
    
        @org.junit.Test
        public void testcountCodeLines(){
            Set<String> filePaths = new HashSet<String>();
            String result = new TooltoCount().countCodeLines(filePaths);
            System.out.println(result);
        }
    
        @org.junit.Test
        public void testcountEmptyLines(){
            Set<String> filePaths = new HashSet<String>();
            String result = new TooltoCount().countEmptyLines(filePaths);
            System.out.println(result);
        }
    
        @org.junit.Test
        public void countNoteLines(){
            Set<String> filePaths = new HashSet<String>();
            String result = new TooltoCount().countNoteLines(filePaths);
            System.out.println(result);
        }
    • 采用junit进行单元测试十分方便高效
    1. 先在E盘新建一个Word Count文件夹和一个test.java
    2. 各项结果

       

       

    程序输入方法:

     因为程序使用args传入参数,所以在控制台使用程序参数进行输入

    输入用例:以下两文件为E盘的文件夹

     

     以及一个实际上的Java源文件,它是放于E盘目录下的

     

     -x结果:

     

     

    7.个人PSP

    PSP2.1

    Personal Software Process Stages

    预估耗时(分钟)

    实际耗时(分钟) 

     Planning

     计划

     30

    15

    ·Estimate 

    ·估计这个任务需要多少时间 

    30 

    30

     Development

    开发 

    1200

    200

     ·Analysis

    ·需求分析 (包括学习新技术)

     120

     150

     ·Design Spec

     ·生成设计文档

     20

     30

     ·Design Review

     ·设计复审(和同事审核设计文档)

     0

     0

     ·Coding Standard

      ·代码规范(为目前的开发指定合适的规范)

     30

    60 

      ·Design

     ·具体设计 

     20

     40

      ·Coding

     ·具体编码 

     150

    2160 

     ·Code Review 

     ·代码复审 

     30

    990

     ·Test

     ·测试(自我测试,修改代码,提交修改) 

     120

    185

    Reporting 

     报告 

     60

     60

     ·Test Report 

     ·测试报告 

     30

     30

     ·Size Measurement  

     ·计算工作量 

    10 

     10

     ·Postmortem & Process Improvement Plan

     事后总结,并提出过程改进计划

     15

     500

    Total

    合计 

    2765

    3308

    8.个人总结

    第一次撰写博客有很多迷茫之处,但是过程中我发现这其实是对整个项目过程的一次回顾与反思。在以前的作业中,通常都是写完代码测试完后就不再关注,也不会反在完成项目的途中犯过什么样的错误。每当下次遇到同样的问题还是会被困扰住,所以我觉得写博客是真的有必要的。我们的目的就在于回顾过程,反思过程中的错误,让项目的过程在我们脑海里留下更深的印象。总的来说,这个项目还没有到完备的阶段。最后,这次的作业的量还是算比较大的,但是却真的能感觉到有很多的收获。很多东西都是词不达意的,真的用心体会过就能明白。也是希望这不完备的代码可以使自己更加完善,更加明白做工一定要做细!

  • 相关阅读:
    util包的常用类及其方法(下)
    util包的常用类及其方法(上)
    每日一记--java基础01
    每日一记--java细节之问01
    每日一记--设计模式01
    每日一记--JVM虚拟机01
    每日一记--java基础之final/static/事务
    每日一记--Mysql错误代码1067
    每日一记--AOP
    每日一记--代理模式
  • 原文地址:https://www.cnblogs.com/MaiZiMaiZi/p/12501517.html
Copyright © 2011-2022 走看看