个人项目作业

1、项目地址:

  https://github.com/ztyh30/wordCount

2、Word Count项目要求:

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

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

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   返回更复杂的数据(代码行 / 空行 / 注释行)。

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

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

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

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

[file_name]: 文件或目录名,可以处理一般通配符。

高级功能:

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

3、实现功能:

-c:返回文件的字符数

-w: 返回文件的单词数

-l:返回文件的行数

-a:返回文件的代码行,注释行,空行

-s:递归处理目录下符合条件的文件,并输出每个文件所有结果

4、预计开发时间psp

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

 

 

· Estimate

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

 30

 30

Development

开发

 

 

· Analysis

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

 120

 180

· Design Spec

· 生成设计文档

 20

 10

· Design Review

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

 10

· Coding Standard

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

 30

 20

· Design

· 具体设计

 30

 20

· Coding

· 具体编码

 480

 630

· Code Review

· 代码复审

 60

 90

· Test

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

 60

 40

Reporting

报告

 

 

· Test Report

· 测试报告

 30

 45

· Size Measurement

· 计算工作量

 20

 20

· Postmortem & Process Improvement Plan

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

 30

 20

合计

 

 920

 1110

5、思路:

通过Java的输入流读取文件,使用String类的各种api来实现各种功能。由于对Java不是很了解,故在菜鸟教程上学习了Java的用法等。

6、设计实现过程:

wc有两个类组成,一个是wc实现类,一个是测试类。实现类中一个函数对应一个功能,由主函数通过输入来调用各个函数。测试类通过junit实现单元测试。

函数:

characterCount(String file) : 统计字符数

lineCount(String file) :统计行数

wordCount(String file) :统计单词数

otherCount(String file) :统计代码行,注释行,空行

searchFileList(String path) :实现文件递归查询

traverseList(String fileName) : 实现对一个文件夹里所有文件执行以上所有函数

7、代码说明:

1.统计字符数

注意要去掉空格的影响

public static int characterCount(String file){
        int character = 0; //字符数
        String s = "";
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(file))));
            while((s = br.readLine())!=null){
                s = s.replaceAll(" ","");
                character += s.length();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return character;
    }

2.统计单词数

对单词的定义:一个或连续的英文字母

通过正则表达式判断,我的判断标准: sdas/sdsad 算是两个单词,而不是一个

public static int wordCount(String file){
        int word = 0; //单词
        String s = "";
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(file))));
            Pattern pattern = Pattern.compile("[a-zA-Z]+");//连续字母即为单词
            while((s = br.readLine()) != null){
                Matcher matcher = pattern.matcher(s);
                while(matcher.find()){
                    word++;
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return word;
}

3.统计行数

如果readLine()方法实现

public static int lineCount(String file){
        int line = 0; //行数
        String s = "";
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(file))));
            while((s = br.readLine()) != null){
                line++;
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return line;
    }

4.统计代码行,注释行,空行

注释行:// }// /* */ 注意,必须以*/结尾在标记着注释行结束

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

通过String类的各种api,来实现判断

特别注意/* */这种注释行,通过flag标记,来判断/*的开始与*/结束,我的判断方式中,只有以*/结尾才使flag为false,其它不在末尾的*/不认为是注释结束

public static String otherCount(String file){
        int spaceline = 0; //空行
        int codeline = 0; //代码行
        int noteline = 0; //注释行
        boolean flag = false; //标记
        String s = "";
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(file))));
            while((s = br.readLine()) != null){
                if(flag == false){
                    if(s.contains("/*") && !s.contains("*/")){
                        flag = true;
                    }
                    if(s.trim().indexOf("//") == 0  || s.trim().indexOf("}//") == 0 || s.trim().indexOf("/*") == 0){
                        noteline++;
                    }
                    else if(s.trim().length() > 1){
                        codeline++;
                    }
                    else{
                        spaceline++;
                    }
                }else{
                    if(s.indexOf("*/") == s.length()-2){
                        flag = false;
                    }
                    noteline++;
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        String result = spaceline+","+noteline+","+codeline;
        return result;
    }

5.递归处理文件夹,把文件加入到集合中

通过file.isDirectory() 判断是否是文件夹,如果是,则递归处理

如果是可读文件,则加入集合

public static List<String> searchFileList(String s){
        File file = new File(s);
        File[] files = file.listFiles();
        if(files == null || files.length == 0){
            System.out.println("ERROR");
            return null;
        }else{
            for(File f : files){
                if(f.isDirectory()){
                    searchFileList(f.getAbsolutePath());//递归处理
                }else if(f.canRead() && f.isFile()){
                    fileList.add(f.getAbsolutePath());//如果是文件,则加入集合
                }else{
                    continue;
                }
            }
        }
        return fileList;
    }

6.对文件集合进行处理

通过 searchFileList() 获得文件集合,并调用以上函数

public static void traverseList(String filename) {
        List<String> fileList = new ArrayList<>();
        fileList = searchFileList(filename);
        if(fileList == null){
            System.out.println("ERROR");
            return;
        }
        for (String s : fileList) {
            int characters = 0;
            int wordCount = 0;
            int lineCount = 0;
            characters = characterCount(s);
            wordCount = wordCount(s);
            lineCount = lineCount(s);
            String str = otherCount(s);
            String[] arr = str.split(",");
            System.out.println("文件" + s + "的信息如下:");
            System.out.println("字符总数:" + characters);
            System.out.println("单词总数:" + wordCount);
            System.out.println("总行数:" + lineCount);
            System.out.println("空行数:" + arr[0]);
            System.out.println("代码行数:" + arr[2]);
            System.out.println("注释总行数:" + arr[1]);
        }
    }

8、测试运行:

-c

-l

-w

-a

测试文件:

测试递归处理文件夹:

覆盖率:

测试文件:

9、总结:

遇到问题:对Java语言的不熟练,如输入流,String类的api,单元测试等,需要花费大量时间去学习。由于缺少开发经验,项目的代码结构很混乱,并且代码冗余。

没有很好地计划,从而开发过程中没有一个好的指导,感觉很杂乱无章。同时,项目的各种功能并没有很好地进行测试。

这次给我的感受就是要做好计划,没有计划,一切都很混乱,开发前的构思比开发重要。要预留多余的时间,实际开发花费的时间比预想的要多许多。

posted @ 2020-03-15 15:39  ztyh30  阅读(173)  评论(0)    收藏  举报