个人项目wordCount

项目的Github地址:https://github.com/KenLoong/wc.git

 

一、项目简介

 

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

 

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

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

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

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

 

 二、PSP表格

 

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

 30

 30

· Estimate

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

 120

 410

Development

开发

 90

 180

· Analysis

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

 30

60

· Design Spec

· 生成设计文档

 10

 10

· Design Review

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

 30

 30

· Coding Standard

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

 20

 10

· Design

· 具体设计

 30

 30

· Coding

· 具体编码

 20

 20

· Code Review

· 代码复审

 10

30

· Test

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

 60

 120

Reporting

报告

 20

 20

· Test Report

· 测试报告

10

 10

· Size Measurement

· 计算工作量

 10

 30

· Postmortem & Process Improvement Plan

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

 10

 10

合计

 

 330

 410

 

三、解题思路

  刚看到题目时,我就想到了要用字符流来读取文件的内容,然后再进行逻辑判断来计算结果。首先是一定要有文件路径的参数,根据这个参数来操作文件。因为跟字符打交道,我设想用StringBuilder这些字符串的包装类来接收文件的内容,再根据它特有的方法来对文本内容进行解析。由于要统计单词,我想要用正则表达式来进行分割。

 

四、设计实现过程

  根据每个需求来创建一个方法来实现功能,所以一共有5个方法,分别来实现-a,-w,-l,-s,-a的功能。只有一个类,这5个方法通过主方法来调用 。

 

五、代码说明

  主方法来接收参数,然后调用其他方法

private static String func;//功能参数
    private static String filePath;//文件路径

    public static void main(String[] args) throws Exception {

        String s="";

        while (true) {
            Scanner scanner = new Scanner(System.in);
            if (scanner.hasNextLine())
                s = scanner.nextLine();

            //-s       C:\\Users\\win10\\Desktop\\测试
            args = s.split("\\s+");

            //判断是否有足够的参数
            if (args.length < 2) {
                System.out.println("请输入足够的参数...");
                continue;
            }
            func = args[0];
            filePath = args[1];
            //判断文件是否存在
            File file = new File(filePath);
            if (!file.exists()) {
                System.out.println("你指定的文件不存在....");
                continue;
            }

            switch (func) {
                case "-w":
                    countWord(null, filePath);
                    break;
                case "-c":
                    countChar(null, filePath);
                    break;
                case "-l":
                    countLine(null, filePath);
                    break;
                case "-s":
                    countDir(filePath);
                    break;
                case "-a":
                    countComplex(filePath);
                    break;
                default:
                    System.out.println("您输入的参数有误");
            }
        }

    }

 

  

统计行数:用BufferedReader来一行一行的读取文件。

public static void  countLine (String fileName,String absolutePath) throws Exception {
        BufferedReader br=new BufferedReader(new FileReader(new File(absolutePath)));
        String line;
        int sum = 0;
        while((line=br.readLine())!=null) {
            sum++;
        }
        System.out.println((fileName==null?"":fileName)+"文件行数为:"+sum);
    }

 

  

统计字符:一行一行的读取,累加长度

public static void  countChar(String fileName,String absolutePath) throws Exception {

        BufferedReader br=new BufferedReader(new FileReader(new File(absolutePath)));
        int sum = 0 ;
        String line;
        while ((line = br.readLine()) != null){
            sum+=line.length();
        }
        System.out.println((fileName==null?"":fileName)+"文件字符数为:"+sum);

    }

 

  

统计单词数:用正则表达式来分割

public static void countWord(String fileName,String absolutePath) throws Exception {

        BufferedReader br=new BufferedReader(new FileReader(new File(absolutePath)));
        int sum = 0 ;
        String line;
        String reg = "[\\s]+";
        while((line=br.readLine())!=null) {
            line = line.replaceAll("[/*{}\\.]","");//去掉注释符号及其他字符
            String[] split = line.split(reg);
            if (!"".equals(split[0]))//排除空行影响
            sum += split.length ;
        }
        System.out.println((fileName==null?"":fileName)+"文件单词数为:"+sum);
    }

 

 

  

复杂统计:统计代码行,注释行,空行

public static void countComplex(String filePath) throws IOException {
        int spaceNum = 0;//空行
        int annoNum = 0;//注释行
        int codeNum = 0;//代码行
        BufferedReader br=new BufferedReader(new FileReader(new File(filePath)));
        String line;
        String reg = "";
        while ( (line = br.readLine()) != null){
            String s = line.replaceAll("[\\s;]", "");
            if (s.length() == 0){//空行
                spaceNum++;
            }else if (s.length() == 1 && ("{".equals(s) || "}".equals(s)) ){//单字符空行
                spaceNum++;
            }else if ( (s.startsWith("{") || s.startsWith("}") ) && s.contains("//")){//单字符的注释行
                annoNum++;
            }else if (s.startsWith("//")){//单行注释
                annoNum++;
            }else if (s.startsWith("/*") && s.length()>=4 && s.endsWith("*/")){//单行注释
               annoNum++;
            }else if (s.startsWith("/*")){//多行注释
                annoNum++;
                while (true){
                    if ((line = br.readLine()) != null){
                        annoNum++;
                        if (line.endsWith("*/"))break;//多行注释结束
                    }else {
                        break;
                    }
                }
            }else {
                codeNum++;//代码行
            }
        }
        System.out.println("文件空行数为:"+spaceNum);
        System.out.println("文件注释行数为:"+annoNum);
        System.out.println("文件代码行数为:"+codeNum);
    }

 

递归统计目录的文件(默认是统计代码行,注释行,空行)

public static void countDir(String filePath) throws Exception {
        File dir = new File(filePath);
        if (!dir.isDirectory() || !dir.exists()){
            System.out.println("你指定的不是目录");
            return;
        }
        File[] files = dir.listFiles();
        for (File file : files) {
            //还有目录,再递归
            if (file.isDirectory()){
                countDir(file.getAbsolutePath());
            }else {
                String name = file.getName();
                String absolutePath = file.getAbsolutePath();
                //调用其他三个方法
                countLine(name,absolutePath);
                countChar(name,absolutePath);
                countWord(name,absolutePath);
            }
        }

    }

 

六、测试

  空文件

  

    

  单行文件

  

   

  一个词文件

  

 

   源文件

  

 

  处理目录的文件

  

 

 七,项目小结

  开发的时间要比我预计的要多很多,可以说是我经验还是太少了。测试也用去了不少时间,说明我的代码安全性考虑得不够好。通过这次项目,我认识到了自己的不足,也学到了新技术,例如如何将java项目转成exe文件。正则表达式以前学过,但这次项目要用到时我还是忘了,又要去查资料,看来我需要多做笔记。

 

    

 

posted @ 2020-03-21 22:44  KenLoong  阅读(181)  评论(0编辑  收藏  举报