码迷,mamicode.com
首页 > 编程语言 > 详细

个人项目(wc.exe)【java】

时间:2020-03-25 01:53:28      阅读:77      评论:0      收藏:0      [点我收藏+]

标签:设计   控制   目录   null   cep   row   限制   str   lips   

一、Github项目地址

https://github.com/pollydeer/code

二、需求分析

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

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

wc.exe [parameter] [file_name]

 

  • 功能列表:
  1. 基本功能:(已实现)

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

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

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

  2.  扩展功能:

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

  3.  高级功能:

    wc.exe -x          //图形界面

 

三、解题思路

  在刚拿到这个题目的时候,其实是有点懵的。因为之前在java里对文件的读写部分知识了解没有很深,所以当时对如何把输入的信息作为参数传入这个点感觉到很困惑。后来我就先查阅了一些资料,了解了如何输入参数这个问题。

  随后,在看到题目的基本功能时,我认为返回行数是在字符数、词数、行数中最简单的、最容易入手的,然后字符数的难度是其次,难度比较高的是词的数目。而且我发现这是一个循序渐进的过程,三个功能之间也有互相借鉴的地方。所以我是从行数开始入手这个项目的。比较重要的是要结合正则表达式对符合条件的字符、单词等进行过滤、筛查。

  由于之前对java的认识只停留在理论层面,真正实践的次数寥寥可数。因此在我决定用java开始,我就开始重新翻看书的相关类的使用、相关方法的使用,也有在网上找一些书上一笔带过的方法,或者根本没细讲的类。

 

四、设计实现过程

  • 基本功能

    我将三个基本功能:统计行数、字符数、词数都封装在了一个Count类里,三个方法分别是CountLine(String filename)、CountWord(String filename)、CountCharacter(String filename)。三者是并列关系。还有一个Main类,里面是main方法,用来调用Count类里的三个方法。除此之外,为了进行单元测试,我建了一个test类包,里面含CountTest类,用来对三个方法进行单元测试。

   1. 统计行的数目

    技术图片

   2. 统计单词的数目

    技术图片

   3. 统计字符的数目

    技术图片

 

五、代码说明

  • 基本功能

  1.统计行的数目

    基本思路是:利用BufferedReader类的readline()方法,实现对行的计数。

 1    public static int CountLine(String filename) {
 2        int LineNum = 0;     
 3        FileReader file = null;   //尚未分配内存空间
 4        BufferedReader brin = null;       //尚未分配内存空间
 5        try {
 6            file = new FileReader(filename);
 7            brin = new BufferedReader(file);
 8            while((brin.readLine()) != null)  {     //循环读取分行文本,判断是否已经读到文件末尾
 9                LineNum++;                    //行数+1
10            }
11            System.out.println("文件的行数为:" + LineNum);
12            brin.close();           //关闭流
13            file.close();
14        }catch (FileNotFoundException e) {
15            System.out.println(filename + "无法在该路径找到文件");
16            return -1;
17        }catch (IOException e) {
18            System.out.println(filename + "输入的文件名有误");
19            return -1;
20        }
21        return LineNum;
22    }

  2.统计单词的个数(注:此处不把数字作为单词计算)

    基本思路是:用正则表达式将非英文字符转化为空格,再根据空格进行分割,这样即可实现分割成一个个词语的功能。

 1    public static int CountWord(String filename) {
 2        String s;
 3        String[] s3 = null;
 4        int WordNum = 0;
 5        FileReader file = null;
 6        BufferedReader brin = null;
 7        try {
 8            file = new FileReader(filename);
 9            brin = new BufferedReader(file);
10            Pattern p = Pattern.compile("[_a-zA-Z]+");      //指定正则表达式的规则为至少匹配一个下划线、大小写英文字母
11            Matcher m = null;
12            while((s = brin.readLine()) != null) {   //分行文本非空时,将分行文本插入到sb中
13                s = s.replaceAll("[^_a-zA-Z]"," ");     //此处认为数字不属于单词,且文件中的单词可含下划线
14                s3 = s.trim().split("\\s+");   //先把两端的空格去掉,再对中间内容根据空格进行分割
15                for(int i = 0; i<s3.length;i++) {
16                    m = p.matcher(s3[i]);      //把s3的每个元素都返回Matcher实例
17                    if(m.matches()) {        //验证s3[i]中的每个元素是否与Pattern.compile的正则表达式模式一致
18                        WordNum++;           //一致则单词数++
19                    }
20                }
21            }
22            System.out.println("文件的单词数为:" + WordNum);
23            brin.close();          //关闭流
24            file.close();          //关闭文件流
25        }catch (FileNotFoundException e) {
26            System.out.println(filename + "无法在该路径找到文件");
27            return -1;
28        }catch (IOException e) {
29            System.out.println(filename + "输入的文件名有误");
30            return -1;
31        }//由于PatternSyntaxException为运行时刻异常,此处不进行处理
32        return WordNum;
33    }

  3.统计字符的个数

    基本思路是:分行读取文本,将读出的内容存入一个字符数组中,当字符非空格时,统计字符数目的变量自增1。

 1   public static int CountCharacter(String filename) {
 2        String s;   
 3        int CharNum = 0;
 4        char[] ch;
 5        FileReader file = null;
 6        BufferedReader brin = null;
 7        try {
 8            file = new FileReader(filename);
 9            brin = new BufferedReader(file);
10            while((s = brin.readLine()) != null) {    //分行读取文本,结果为string类型
11                ch = s.toCharArray();  //将一行读取出来的内容存入字符数组中
12                for(char temp : ch) {      //遍历ch数组,如果发现有空格则不对CharNum进行++操作
13                    if(temp != ‘ ‘) {
14                        CharNum++;
15                    }
16                }
17            }
18            System.out.println("文件的字符数为:" + CharNum);
19            brin.close();        //关闭流
20            file.close();
21        }catch (FileNotFoundException e) {
22            System.out.println(filename + "无法在该路径找到文件");
23            return -1;
24        }catch (IOException e) {
25            System.out.println(filename + "输入的文件名有误");
26            return -1;
27        }
28        return CharNum;
29    }

  4.Main函数

 1     public static void main(String[] args) throws IOException,ArrayIndexOutOfBoundsException{
 2         int i;
 3         String temp = null;
 4         System.out.println("请输入命令:");
 5         Scanner input = new Scanner(System.in);     //从cmd输入控制参数及file_name
 6         if(input.hasNext()) {
 7                 temp = input.nextLine();             //结束扫描的输入
 8             }
 9             String[] strwords = temp.split(" ");         //用空格分隔输入的参数以及文件名
10             String filename = strwords[strwords.length-1];     //路径为输入的最后一个参数
11             
12             
13             for(i = 0; i<strwords.length-1; i++)   //从开头到文件名字前面都是属于parameter
14                 {
15                     if(strwords[i].equals("-c")) 
16                         Count.CountCharacter(filename);
17                     if(strwords[i].equals("-w"))
18                         Count.CountWord(filename);
19                     if(strwords[i].equals("-l"))
20                         Count.CountLine(filename);
21                 }
22             input.close();   //关闭流   
23     }

 

六、测试运行

  • 基本功能

   各文件的内容截图:

技术图片

  测试运行的截图:

  1.空文件(test1.c)

 技术图片

  2.只有单个字符(test2.c)

技术图片

  3.只有单行(test3.c)

技术图片

  4.完整源代码(test4.c)

技术图片

 

★单元测试及代码覆盖率测试(注:此处仅以统计字符个数方法的截图为例,其他方法以相同方法进行测试)

  • 单元测试

  1.代码

package test;

import static org.junit.Assert.*;

//import org.junit.Before;
import org.junit.Test;

import src.Count;

import org.junit.Ignore;

public class CountTest {

    
    @Ignore
    public void setUp() throws Exception {
    }

    @Test
    public void testCountChar() {
        assertEquals(6,Count.CountCharacter("C:\\Users\\Dell\\Desktop\\test100.txt"));
    }

    @Test
    public void testCountWord() {
        assertEquals(2,Count.CountWord("C:\\Users\\Dell\\Desktop\\test\\test3.txt"));
    }
    
        
    @Test
    public void testCountLine() {
        assertEquals(1,Count.CountLine("C:\\Users\\Dell\\Desktop\\test\\test3.txt"));
    }
}

  2.截图(以统计字符个数方法的单元测试为例进行截图)

技术图片

上图左侧的绿色表示测试通过且无误。

 

技术图片

上图的红色矩形表示测试有部分失败,可以看到,正确的文件字符数为8,而我在testCountChar方法中,输入的文件字符期望值是6,两数不一致,因此测试失败。

 

技术图片

 

上图也是出现了测试失败的问题。原因是我手动把文件的路径设成了一个不存在的文件“test100.txt”,且在设计CountChar方法时,我把FileNotFoundException异常设计成了方法的返回值为-1。而此处在测试时,我输入的期望字符数是6,两数不一致,从而测试失败。

 

  3. 代码覆盖率

技术图片

 

上图为程序正常运行时的代码覆盖率截图。

 

 

技术图片

上图为程序出现异常时的代码覆盖率截图。

 

技术图片

 

上图为单元测试时的代码覆盖率截图。

 

七、PSP

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

 30

 40

· Estimate

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

 30

 40

Development

开发

 370

 476

· Analysis

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

 40

 90

· Design Spec

· 生成设计文档

 10

 15

· Design Review

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

 10

 10

· Coding Standard

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

 10

 8

· Design

· 具体设计

 60

 48

· Coding

· 具体编码

 200

 175

· Code Review

· 代码复审

 30

 40

· Test

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

 60

 90

Reporting

报告

 100

 100

· Test Report

· 测试报告

 30

 60

· Size Measurement

· 计算工作量

 30

 20

· Postmortem & Process Improvement Plan

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

 40

 30

合计

 

 550

 616

 

八、项目小结

  总得来说,这是一次对自己很好的一个锻炼机会。因为之前学java的时候都是简单停留在理论上,可以说是知识还在书里,并没有被吸收、内化。这次决定用java来写个人项目真的是把理论变为实践的一次很好的尝试,期间磕磕碰碰也遇到了很多问题。归根结底还是熟悉度的问题。

  因为我是初次尝试用eclipse进行单元测试和代码覆盖率的测试,期间摸索如何进行单元测试也耗费了比较多的时间,实际编码的时间其实相对来说并不算很长。但是我在这个过程中也发现对于main方法如何书写是比较陌生的,特别是要传入参数的时候比较束手无策。其次,在这个过程中,我也辨别了StringBuffer类、BufferedReader类、StringReader类等等很容易混淆的类,也熟悉了一些,当然还需要后期再继续使用熟悉一下。除此之外,在这个过程中我也发现每个类是有很多很多的方法可以使用的,在实际应用时必须得弄清作用才能让逻辑正确。

  这次因为初次尝试用java写,的确熟悉度是一个很大的限制因素。在这次个人项目中,我实现了基本功能,也把过程都尽量完整记录。但是可惜的是扩展功能和高级功能都未能实现,可以在之后继续把剩下的任务钻研、完成,多把在这个过程中得到的经验都汲取、吸收、内化了。

 

个人项目(wc.exe)【java】

标签:设计   控制   目录   null   cep   row   限制   str   lips   

原文地址:https://www.cnblogs.com/pollydeer/p/12563367.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!