WordCount程序(java)

 Github项目地址:https://github.com/czmDeRepository/SoftwareWork/tree/master/work

一、题目描述

  •  实现一个简单而完整的软件工具(源程序特征统计程序)。
  •  进行单元测试、回归测试、效能测试,在实现上述程序的过程中使用相关的工具。
  •  进行个人软件过程(PSP)的实践,逐步记录自己在每个软件工程环节花费的时间。

二、WC 项目要求

  • wc.exe 是一个常见的工具,它能统计文本文件的字符数、单词数和行数。这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数、单词数和行数。
  • 实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。
  • 具体功能要求:程序处理用户需求的模式为:wc.exe [parameter] [file_name]

三、核心代码

  • 获取文件字符缓存流
private static BufferedReader GetFileInmputStream(String fileName){
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
        } catch (FileNotFoundException e) {
           System.out.println("系统找不到指定路径文件");
        }
        return bufferedReader;
    }
  • 返回文件字符数
public static int CharCount(String fileName){
        BufferedReader in = null;
        int count = 0;
        in = GetFileInmputStream(fileName);
        if (in == null){
            return ERROR_NUM;
        }
        int result = ERROR_NUM;
        try {

            while((result = in.read()) != -1){
                if(result != '
' && result!='
'){
                    count++;
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return count;
    }
  • 返回文件行数
public static int LineCount(String fileName){
        BufferedReader read = null;
        int count = 0;
        read = GetFileInmputStream(fileName);
        if (read == null){
            return ERROR_NUM;
        }
        try {
            while (read.readLine() != null){
                count++;
            }

//                速度较前者慢
//            Iterator<String> iterator = read.lines().iterator();
//            while (iterator.hasNext()){
//                iterator.next();
//                count++;
//            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(read != null){
                try {
                    read.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return count;
    }
  • 返回文件单词数
public static int WordCount(String fileName){
        BufferedReader in = null;
        int count = 0;
        in = GetFileInmputStream(fileName);
        if (in == null){
            return ERROR_NUM;
        }
        try {
            String str = null;
            while((str = in.readLine()) != null){
                //\s+表示 空格,回车,换行等空白符
                String[] split = str.split("\s+");
                count += split.length;
            }

        }  catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

        return count;
    }
  • 显示(代码行 / 空行 / 注释行)
public static void Complex(String filename){
        int codeLine = 0;
        int annotationLine = 0;
        int blankLine = 0;
//        判断是否处于多行注解内
        boolean flag = false;
        BufferedReader bufferedReader = GetFileInmputStream(filename);
        if (bufferedReader == null){
            return;
        }
        String strLine = null;
        String newLine = null;
        try {
            while ((strLine = bufferedReader.readLine())!= null){
                if (flag) {
                    if (strLine.endsWith("*/")){
                        flag = false;
                    }
                    annotationLine++;
                }else {
//                  去除空格
                    newLine = strLine.replaceAll("\s*", "");
                    if("".equals(newLine)){
                        //空行
                        blankLine++;
                    }else if (newLine.startsWith("/*")){
                        //注释行
                        if (!newLine.endsWith("*/")){
                            //去除/*单行注释*/情况
                            flag = true;
                        }
                        annotationLine++;
                    }else if (newLine.startsWith("//") || newLine.startsWith("}//")){
                        //注释行
                        annotationLine++;
                    }else {
                        //代码行
                        codeLine++;
                    }
                }
            }
            System.out.println("代码行:"+codeLine);
            System.out.println("空行:"+blankLine);
            System.out.println("注释行:"+annotationLine);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (bufferedReader != null){
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
  • 递归处理目录
public static void FolderCount(String operation, String folderName, String fileName){
        File file = new File(folderName);
        if(file.isDirectory()){
            int index = fileName.lastIndexOf('.');
            if(index >= 0){
                String extension = fileName.substring(index);
                String frontName = fileName.substring(0, index);
                File[] fileList = file.listFiles();
                if (fileList.length > 0){
//                    String regex = ".*"+name+"\.+"+extension+"$";
//                    for (String f:fileList){
//                        System.out.println(Pattern.matches(regex, f));
//                        System.out.println(f);
//                    }

//                    递归遍历
                    if (!ReadFold(operation, file.getName(), fileList, frontName, extension)){
                        System.out.println("该目录下无对应文件");
                    }
                }else{
                    System.out.println("该目录为空");
                }
            }

        }else{
            System.out.println("参数不是文件夹或路径错误");
        }

    }

    /***
     * 递归子文件
     * @param operation
     * @param fileList
     * @param frontName
     * @param extension
     */
    public static boolean ReadFold(String operation, String parentName, File[] fileList, String frontName, String extension){
        boolean flag = false;
        boolean childFlag = false;
        String fName = null;
        for (File f:fileList){
            //    子文件是文件
            if(f.isFile()){
                fName = f.getName();
                if (fName.indexOf(frontName) >=0 && fName.endsWith(extension)) {
                    switch (operation) {
                        case "-c":
                            System.out.println("【"+parentName+"】下的【"+fName+"】文件的字符数:" + CharCount(f.getPath()));
                            break;
                        case "-w":
                            System.out.println("【"+parentName+"】下的【"+fName+"】文件的单词数:" + WordCount(f.getPath()));
                            break;
                        case "-l":
                            System.out.println("【"+parentName+"】下的【"+fName+"】文件的行数:" + LineCount(f.getPath()));
                            break;
                        case "-a":
                            System.out.println("【"+parentName+"】下的【"+fName+"】文件的信息:");
                            Complex(f.getPath());
                            break;
                        default:
                            System.out.println("第二参数错误(-c,-w,-l)");
                            return false;
                    }
                    flag = true;
                }
            }else{  //子文件是目录
                childFlag = ReadFold(operation, f.getName(), f.listFiles(), frontName, extension) || childFlag; 

      }
    } 

  return (flag || childFlag);
}
  •  主函数调用
  /**
     * 正确传参
     */
    private static int FLAG_TWO = 2;

    /**
     * 出错误返回值
     */
    private static int ERROR_NUM = -1;

    public static void main(String[] args) {

        if(args.length >= FLAG_TWO){
            switch (args[0]){
//                字符数
                case "-c":
                    long startC = System.currentTimeMillis();
                    System.out.println("字符数:"+CharCount(args[1]));
                    System.out.printf("耗时%d(毫秒)
", System.currentTimeMillis()-startC);
                    break;
//                 单词数
                case "-w":
                    long startW = System.currentTimeMillis();
                    System.out.println("单词数:"+WordCount(args[1]));
                    System.out.printf("耗时%d(毫秒)
", System.currentTimeMillis()-startW);
                    break;
//                  行数
                case "-l":
                    long startL = System.currentTimeMillis();
                    System.out.println("行数:"+LineCount(args[1]));
                    System.out.printf("耗时%d(毫秒)
", System.currentTimeMillis()-startL);
                    break;
//                  递归处理目录下符合条件的文件。
                case "-s":
                    if(args.length == 4){
                        long startS = System.currentTimeMillis();
                        FolderCount(args[1], args[2], args[3]);
                        System.out.printf("耗时%d(毫秒)
", System.currentTimeMillis()-startS);
                    }else{
                        System.out.println("正确格式为:wc.exe -s 【操作】 文件夹路径 文件名");
                    }
                    break;
//                  返回更复杂的数据(代码行 / 空行 / 注释行)。
                case "-a":
                    long startA = System.currentTimeMillis();
                    Complex(args[1]);
                    System.out.printf("耗时%d(毫秒)
", System.currentTimeMillis()-startA);
                    break;
                default:
                    System.out.println("请输入正确参数【操作】+文件路径");
            }
        }else {
            System.out.println("请输入正确参数【操作】+文件路径");
        }

    }

四、项目测试

  • 用exe4j将jar包转exe程序再测试

 五、PSP

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

 10

 15

· Estimate

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

200

 300

Development

开发

 120

 200 

· Analysis

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

15 

 10

· Design Spec

· 生成设计文档

 10

 10

· Design Review

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

 10

 10

· Coding Standard

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

 5

 5

· Design

· 具体设计

 30

 25

· Coding

· 具体编码

 100

200

· Code Review

· 代码复审

 10

 15

· Test

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

 10

 30

Reporting

报告

 15

 20

· Test Report

· 测试报告

 10

 30

· Size Measurement

· 计算工作量

 15

 20

· Postmortem & Process Improvement Plan

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

 15

 30

合计

575

920

六、总结

  实际时间总比预期长,敲代码容易改代码难,思路要清晰,读取文件用缓冲流效果更好,将jar包转exe再执行程序感觉比直接运行慢,” || “判断只要前者为真后者就不再执行!!!学会了简单使用git管理项目。

原文地址:https://www.cnblogs.com/chzhm/p/12501338.html