WordCount基础功能设计(java)

WordCount基础功能设计(java)

WordCount的需求可以概括为:对程序设计语言源文件统计字符数、单词数、行数,统计结果以指定格式输出到默认文件中,以及其他扩展功能,并能够快速地处理多个文件。

可执行程序命名为:wc.exe,该程序处理用户需求的模式为:

wc.exe [parameter] [input_file_name]

存储统计结果的文件默认为result.txt,放在与wc.exe相同的目录下。

===============================================================

基础功能:

 -c 统计源文件字符
 -l  统计源文件行数
-w 统计源文件单词
 -o 输出统计数据到指定文件

PSP表格

PSP2.1 PSP阶段 预估耗时(分钟) 实际耗时(分钟)
Planning 计划  30  20+10+15+10(开发中修改计划)
· Estimate · 估计这个任务需要多少时间  10  5
Development 开发  300  450
· Analysis · 需求分析 (包括学习新技术) 60  60
· Design Spec · 生成设计文档  30  0
· Design Review · 设计复审 (和同事审核设计文档)  30  0
· Coding Standard · 代码规范 (为目前的开发制定合适的规范)  10  10
· Design · 具体设计  30  60
· Coding · 具体编码  300  450
· Code Review · 代码复审  30  0
· Test · 测试(自我测试,修改代码,提交修改)  15  30
Reporting 报告  30  0
· Test Report · 测试报告  30  0
· Size Measurement · 计算工作量  5  5
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划  30  30
  合计 940 1100

代码设计

一共使用三个类

commandsScanner类负责读取用户输入的命令并调用myFunction的对应方法

myFunction类集成对用户输入命令的处理

WordCount类是主类

1.CommandScanner类

CommandsScanner类只有一个方法 void comScanner(String input)
该方法读取输入的字符串,使用split(“ ”)方法分隔空格并保存到commands[ ]字符串数组中
该方法能分离文件路径和命令具体采用了endsWith()方法和equals()方法
并能判断是否为有效命令



public class CommandScanner
{
    public void comScanner(String input)//传入的命令,是一个字符串
    {
        MyFunction myFunc=new MyFunction();
        String inFileName = null;
        String outFileName=null;
        String[] commands=input.split(" ");//分隔命令
        for(int i=0;i<commands.length;i++)
        {
            if(commands[i].endsWith(".c"))//判断是否为待统计文件
            {
                inFileName=commands[i];
            }
            else if(commands[i].endsWith(".txt"))//判断是否为待写入文件
            {
                outFileName=commands[i];
            }
        }
        for(int i=0;i<commands.length-1;i++)//对命令数组进行switch操作判断具体操作
        {
            //判断是否为合法命令
            if(!(commands[i].equals("-c")||commands[i].equals("-l")||commands[i].equals("-w")||commands[i].equals("-o")||commands[i].endsWith(".c")||commands[i].endsWith(".txt")))
            {
                System.out.println("command \""+commands[i]+"\" is not a proper order");
            }
            
            //判断具体是什么命令
            if(commands[i].equals("-c")||commands[i].equals("-l")||commands[i].equals("-w")||commands[i].equals("-o"))
            {
            switch (commands[i]) {
            case "-c":
                myFunc.charCounter(inFileName);
                break;
            case "-w":
                myFunc.wordCounter(inFileName);
                break;
            case "-l":
                myFunc.lineCounter(inFileName);
                break;
            case "-o":
                myFunc.outPut(inFileName,outFileName);
                break;
            default:
                System.out.println("wrong command orders!");
                break;
            }
        }
    }
}
}

2.MyFunction类

这是myFunction的主要方法,也是整个项目主要的核心

void fileReader(String fileName) 该方法接受源文件(待统计文件)路径,并且对此文件进行统计操作
每次读取一行并且统计长度,“-c”命令得到
每读取一行lineCount++,“-l”命令得到
每一行使用正则表达式(“\w+”),该正则表达式判断多个字母或者下划线或者数字组合的字符串,寻找到wordCount++,“-w“命令得到
注意事项:每次使用readLine()需要使用一个字符串来保存并操作字符串,不这样做直接操作readLine()读出的一列字符串会导致跳行读取,导致结果不准确

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MyFunction
{
    public int CharCount=0;//字符计数器
    public int WordCount=0;//单词计数器
    public int LineCount=0;//行数计数器
    public int callCounter=0;//调用次数计数器,保存调用方法次数
    
    public void fileReader(String fileName)throws IOException
    {
        File file=new File(fileName);
        if(file.exists()) {
        BufferedReader br=new BufferedReader(new FileReader(fileName));
        String lineStrSaver=null;//保存每行字符串,否则会出现跳行读取
        while((lineStrSaver=br.readLine())!=null)//不为空行
        {
            CharCount+=lineStrSaver.length();//单句字符数
            LineCount++;
            
            Pattern pattern=Pattern.compile("\\w+");//正则表达式判断是否为“单词”
            Matcher matcher=pattern.matcher(lineStrSaver);//匹配当前读取行的字符串
            while(matcher.find())//若找到
            {
                WordCount++;//单词数++
            }
        }
        br.close();
        callCounter ++;//多次调用此函数的计数器
        }
        else {
            System.out.println("this file doesn't exist...");
        }
    }
}

这是三个具体实现用户命令的方法

注意事项:当用户输入多个命令组合时会重复调用fileReader()方法,导致计数器重复递加
所以定义了一个变量callCount,用以保存调用次数,得到的字符数/行数/单词数 每次都应该除以此计数器,才是正确的字符数

public void charCounter(String filename)
    {
        try {
            fileReader(filename);
            System.out.println("character number is :"+CharCount/callCounter);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public void wordCounter(String filename)
    {
        try {
            fileReader(filename);
            System.out.println("word number is :"+WordCount/callCounter);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public void lineCounter(String filename)
    {
        try {
            fileReader(filename);
            System.out.println("line number is :"+LineCount/callCounter);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

这是“-o”命令的实现方法,采用fileWriter()和bufferWriter写入文件

注意事项:写入完成后必须关闭bufferWriter否则文件写入将不成功

public void outPut(String infilename,String outfiename)
    {
        try {
            fileReader(infilename);
            File file=new File(outfiename);

            if(!file.exists())
            {
                file.createNewFile();
            }
            String charSents="character number is ";
            String lineSents="line number is ";
            String wordSents="word number is ";
            String charCon=CharCount/callCounter+"";
            String lineCon=LineCount/callCounter+"";
            String wordCon=WordCount/callCounter+"";
            charSents=charSents.concat(charCon).concat("\r\n");//使用concat()方法链接两个字符串
            lineSents=lineSents.concat(lineCon).concat("\r\n");
            wordSents=wordSents.concat(wordCon).concat("\r\n");
//          FileWriter fileWriter=new FileWriter(file.getName(),true);//在构造方法中传入true ,重复运行才不会丢失
            FileWriter fw=new FileWriter(file.getAbsoluteFile());
            BufferedWriter bWriter=new BufferedWriter(fw);
            bWriter.write(charSents);//写入到文件
            bWriter.write(lineSents);
            bWriter.write(wordSents);
            bWriter.close();//必须关闭才能写入文件,否则写入无效
            fw.close();
            if(file.length()!=0)
                System.out.println("write file succeed...");
            else
                System.out.println("write file failed...");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

测试:


public class WordCountTest {
    public static void main(String[] args) {
        //测试输入错误指令
        System.err.println("test wrong command:");
        String str1="-a F:\\test\\a.c";
        CommandScanner cs=new CommandScanner();
        cs.comScanner(str1);
        System.out.println();
        
        //测试正确输入命令
        System.err.println("test proper command:");
        String str2="-c F:\\test\\a.c";
        CommandScanner cs2=new CommandScanner();
        cs2.comScanner(str2);
        System.out.println();
        
        //测试输入多个命令
        System.err.println("test multiple command:");
        String str3="-c -l -w F:\\test\\a.c";
        CommandScanner cs3=new CommandScanner();
        cs3.comScanner(str3);
        System.out.println();
        
        //测试-o功能
        System.err.println("test \"-o\" command:");
        String str4="-c F:\\test\\a.c -o F:\\test\\result.txt";
        CommandScanner cs4=new CommandScanner();
        cs4.comScanner(str4);
        System.out.println();
        
        //测试输入错误源文件路径
        System.err.println("test wrong file path:");
        String str5="-c F:\\test\\b.c";
        CommandScanner cs5=new CommandScanner();
        cs5.comScanner(str5);
        System.out.println();
    }
}

运行结果:


***************************************************************************************

***************************************************************************************

***************************************************************************************

***************************************************************************************

第一阶段总结:

这个项目总体来说不难,最开始准备使用C语言实现,但是没有和另一个主学习Java小组成员沟通好,最后转向使用Java实现此项目。因为我的Java还没学习完,所以刚开始上手的时候学习了一些新的东西,不是很熟,也是在慢慢的实验中改正,然后修正了很多上面注释的注意事项等等细节才让基础功能实现,所以整体的项目进度拉得比较长,而且实际要求功能没有达到完全实现,有些逻辑还没有加上,达到完全的100%完成度,回过头来看,应该分析好输入/输出,因为在编码过程中发现了很多需要回过头去增加输入多样性支持的操作,让代码改来改去,如同系统分析所学的,代码容易修改,但是容易出错和容易引起连锁反应,增加工作量。总体来说体会到了PSP表格的优点,能让人一眼看出自己的时间分配,长此以往使用PSP表格就能改正自己开发过程中的一些不合理时间分配,提高开发效率。
对于编写博客,也是第一次编写博客,排版很成问题,美观程度不足,希望能在慢慢的写博客过程中改善这一点,让自己的学习笔记更加赏心悦目,以后能回过头轻易的找到以往的难点或者心得体会,也很好。
还有其实已经打包好EXE文件,但是会将我使用的err.out当错误处理,这里就直接在控制台演示程序。有部分逻辑加上会使用户好感度增加,将在第二阶段时一并加上,优化代码。

skr

猜你喜欢

转载自www.cnblogs.com/Leonard12138/p/9695007.html