zoukankan      html  css  js  c++  java
  • 软件工程:java实现wordcount基本功能

    github链接:https://github.com/Nancy0611/wc

    一:项目相关要求

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

      程序处理用户需求的模式为:wc  [parameter]  [file_name]

    二:项目功能完成情况

      基本功能:

    • wc  -c  <file>  统计文件的字符数(完成)
    • wc  -w <file>  统计文件词的数目(完成)
    • wc  -l   <file>  统计文件的行数 (完成)

      扩展功能:

    • wc  -s  <file>  递归处理目录下符合条件的文件(已完成)
    • wc  -a  <file>  返回更复杂的数据:代码行 / 空行 / 注释行(已完成)

      说明:

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

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

      注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释:} //注释,在这种情况下,这一行属于注释行。

      高级功能:

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

    三:设计思路

    1. 获取输入命令行参数,利用正则表达式校验输入命令行是否符合格式

    2. 如果输入命令符合格式要求则利用split(" ")按照空格将命令拆开并存储于数组

    3. 获取命令数组的最后一个元素,即为待统计的文件名或目录

    4. 若输入为文件则直接进行统计,若输入为目录则通过递归处理目录下的文件 

    5. 输入参数[-c] [-w] [-l] [-a] 初始值设为false,一旦输入将值置为true以此选择性地显示

    6. 根据不同的命令对数据进行相应的处理

      • 字符数:获取每行的字符数,逐行叠加

      • 词的数目:获取每行除去空格的字符数,逐行叠加
      • 行数:利用readline()不为 null,逐行叠加

      • 空行:利用正则表达式统计只含"{"或 "}"或 " "的行数
      • 注释行:统计除去"//"、"{//"、"/*"开头、"*/"结尾、"/* 单行注释 */"、"/*多行注释*/"

      • 代码行:总行数除去代码行和空行即可得

    四:设计思路

    五:代码说明

    程序入口,获取输入命令行,检验后若符合格式,则将命令解析并调用相关功能函数

     1 public static void main(String[] args) throws IOException {
     2         
     3         scan = new Scanner(System.in);
     4         String commend=scan.nextLine();
     5         boolean result=checkInput(commend);
     6         //输入格式为:wc [parameter] [file_name]
     7         
     8         if(!result){
     9             System.out.println("输入指令不符格式");
    10         }else{
    11             String[] comArray=commend.split(" ");
    12             int comLength=comArray.length;
    13             String File_name=comArray[comLength-1];//获取文件名
    14             ArrayList<File> ff = new ArrayList<File>();
    15             getFromFile_name(File_name);
    16         
    17             for(File perfile:file){
    18                 br=new BufferedReader(new FileReader(perfile));
    19                 countData(br);
    20             }
    21             status(comArray,comLength);//修改cwl状态
    22             display(c,w,l,a);//显示
    23             br.close();
    24         }
    25     }

    正则表达式检验输入命令行格式

     1 public static boolean checkInput(String input){//正则表达式校验输入命令行
     2         boolean flag=false;
     3         try{
     4             String pattern="^wc\s+(\-[cwlas]\s+){1,5}\s*\S+$";
     5             Pattern  regex=Pattern.compile(pattern);
     6             Matcher matcher=regex.matcher(input);
     7             flag=matcher.matches();
     8         }catch(Exception e){
     9             flag=false;
    10         }
    11         return flag;
    12     }

    根据输入文件名或文件路径获取文件

     1 public static ArrayList<File> getFromFile_name(String path){
     2         File f=new File(path);
     3         file=new ArrayList<File>();
     4         if(f.isFile()&&f.exists()){
     5             file.add(f);
     6         }else if(f.isDirectory()){
     7             File[] files=f.listFiles();
     8             for(File fis: files){
     9                 if(fis.isFile()){//文件
    10                     file.add(fis);
    11                 }else if(fis.isDirectory()){//目录 
    12                     //System.out.println(fis.getAbsolutePath());
    13                     getFromFile_name(fis.getAbsolutePath());
    14                 }
    15             }
    16         }
    17         return file;
    18     }

    根据输入命令行的解析结果修改c w l a的状态,输入含有以上字符则标记为true

     1 public static void status(String[] comArray,int comLength){//修改cwla状态
     2         for(int i=0;i<comLength;i++){
     3             switch(comArray[i]){
     4             case "-c": 
     5                 c=true;
     6                 break;
     7                 
     8             case "-w":
     9                 w=true;
    10                 break;
    11                 
    12             case "-l":
    13                 l=true;
    14                 break;
    15                 
    16             case "-a":
    17                 a=true;
    18                 break;
    19             
    20             default:
    21                 break;
    22             }
    23         }
    24     }

    根据标记的c w l a的值来选择显示的内容

     1 public static void display( boolean c,boolean w,boolean l,boolean a){
     2         //选择显示部分
     3         if(c){
     4             System.out.println("字符数:"+countChar);
     5         }
     6         if(w){
     7             System.out.println("词的数目:"+countWord);
     8         }
     9         if(l){
    10             System.out.println("行数:"+countLine);
    11         }
    12         if(a){
    13             System.out.println("代码行:"+codeLine+"
    空行:"+blankLine+"
    注释行:"+commentLine);
    14         }
    15     }

    计算功能

     1 public static void countData(BufferedReader br){//计算部分
     2         boolean comment=false;
     3         try {
     4             while((line=br.readLine())!=null){
     5                 /*统计字符数 */
     6                 countChar+=line.length();
     7                 /*统计词的数目 */
     8                 countWord+=line.split(" ").length;
     9                 /*统计行数 */
    10                 countLine++;
    11                 line=line.trim();
    12                 /* 统计空行*/
    13                 if(line.matches("[\s&&[^\n]]*$")){
    14                     blankLine++;
    15                 }else if(line.equals("{")||line.equals("}")){
    16                     blankLine++;
    17                 /* 统计注释行 */
    18                 }else if(line.startsWith("/*")&&!line.endsWith("*/")){
    19                     commentLine++;
    20                     comment=true;
    21                 }else if(true==comment){
    22                     commentLine++;
    23                     if(line.endsWith("*/")){
    24                         comment=false;
    25                     }
    26                 }else if(line.startsWith("//")){
    27                     commentLine++;
    28                 }else if(line.startsWith("/*")&&line.endsWith("*/")){
    29                     commentLine++;
    30                 }else if(line.startsWith("}//")){
    31                     commentLine++;
    32                 /*统计代码行 */
    33                 }else{
    34                     codeLine++;
    35                 }
    36             }
    37             
    38         } catch (IOException e) {
    39             // TODO Auto-generated catch block
    40             e.printStackTrace();
    41         }
    42         
    43     }

    六:测试截图

    • 根据文件名统计(非递归)

      输入命令

    wc -c -l -w -a  E:	est	est1.txt

      文件截图:

      测试结果:

    • 根据文件路径统计(递归处理)

      输入命令:

    wc -s -c -l -w -a  E:	est

      文件截图:

      E: est est1.txt

      E: estseles est2.txt

      测试结果:

    七:PSP时间统计

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

    八:项目总结

      关于wordcount,首先,一开始的构思是先读取文件,一段时间没有使用java,对io流的相关内容不是很熟悉,成功将文件存进ArrayList中后我没有考虑到Array List变量之间的赋值问题,直接用=去赋值,发现取出的数据出错,经过上网搜索了解了关于ArrayList对象之间赋值该注意的问题,收获不少。其次,对输入指令格式的验证问题,由于之前没有接触过正则表达式,在正则表达式的相关内容上花费了挺多时间。最后,关于项目编程还是要多实践,本次课程设计一开始都是停留在想的阶段,一直没怎么实践,结果发现过去了挺长时间仍旧没有进度。经过这次课程设计,温习了java的相关内容,同时又发现了许多新的问题,在解决问题的过程受益匪浅。

  • 相关阅读:
    Nginx的启动、停止与重启
    如何修改element.style中的值
    在centos后台运行python程序(nohup)
    Python schedule 模块使用
    「Django」Django内置email发送邮件
    Django内置email发送邮件
    「Django」Xadmin应用
    「Django」浏览+1的操作
    「Vue」watch基本用法
    「Django」contenttypes基本用法
  • 原文地址:https://www.cnblogs.com/nancy12/p/9648206.html
Copyright © 2011-2022 走看看