个人项目(WordCount)

GitHub:https://github.com/yozyyyqls/WordCounter

1.0 PSP表格

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

 90

 70

· Estimate

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

5

扫描二维码关注公众号,回复: 10095508 查看本文章

10

Development

开发

 600

 960

· Analysis

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

 300

 400

· Design Spec

· 生成设计文档

 30

 30

· Design Review

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

 10

 6

· Coding Standard

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

 60

 120

· Design

· 具体设计

 60

 120

· Coding

· 具体编码

 600

 720

· Code Review

· 代码复审

 30

 60

· Test

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

 45

 60

Reporting

报告

 20

 15

· Test Report

· 测试报告

 30

 20

· Size Measurement

· 计算工作量

 5

 10

· Postmortem & Process Improvement Plan

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

 10

 10

合计

1895

 2611

1.1 WC 项目要求

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

需求举例:

wc.exe -s -a *.c

返回当前目录及子目录中所有*.c 文件的代码行数、空行数、注释行数。

1.2 解题思路描述

  • 题目涉及文件操作,肯定需要用到IO流的操作。
  • 基础功能部分:
    • 计算字符数和单词数直接用正则表达式去匹配;
    • 计算行数则计算回车的数量,最后加一。
  • 扩展功能部分:
    • 计算注释行按行读取,再使用正则去匹配;
    • 计算空白行先按行读取,将每行首尾的空白字符去除,剩余字符数为0或者1的则为空白行;
    • 计算代码行,如果按行读取时不满足以上的两个条件,则该行为代码行。
  • 高级功能部分:
    • 使用javafx

1.3 设计实现过程

包目目录结构:

各模块依赖关系:

1.4 关键代码说明

  • 基础功能部分核心代码

public enum CountImpl implements Count {
    OP_C{
        @Override
        public int op(byte[] fileByte) {
            if(fileByte==null) return 0;    //文件为空
            String fileStr = new String(fileByte);
            String pattern = "\\S";
            return FileUtil.searchStr(pattern, fileStr);
        }
    },


    OP_W{
        @Override
        public int op(byte[] fileByte){
            if(fileByte==null) return 0;
            String fileStr = new String(fileByte);
            String REGEX = "[a-zA-Z]+\\W";
            return FileUtil.searchStr(REGEX, fileStr);
        }
    },


    OP_L{
        @Override
        public int op(byte[] fileByte){
            if(fileByte==null) return 0;
            String REGEX = "\\n";
            String fileStr = new String(fileByte);
            return FileUtil.searchStr(REGEX, fileStr)+1;//最后一行通常无回车
        }
    };
}
  • 扩展功能部分核心代码

/**
 * 批量处理文件
 * @param subModel 选择的处理模式
 * @param filePath 文件绝对路径
 * @throws IOException 文件不存在
 */
public static void batchProCount(String subModel, String filePath) throws IOException {
    File file = new File(filePath);
    int num=0;
    if(file.isFile()){//如果是文件
        byte[] fileByte = FileUtil.fileToByte(filePath);
        num = CountImpl.valueOf(subModel).op(fileByte);//根据模式的不同自动分辨使用哪个函数
        System.out.println("文件路径:"+file.getAbsolutePath());
        System.out.println("计算结果:"+ num +"\n");
    }else if(file.isDirectory()){//如果是目录
            File[] fileList = file.listFiles();
            if(fileList==null) {//如果该目录下无文件
                System.out.println("文件不存在");
                return;
            }
            for (File value : fileList) {
                batchProCount(subModel, value.getAbsolutePath()); //递归处理
            }
        }
}




/**
 *计算文件代码行数、注释行数、空白行数
 * @param filePath 文件路径
 * @return num[0]为代码行数,num[1]为注释行数,num[2]为空白行数
 * @throws IOException 文件不存在
 */
public static int[] proCount(String filePath) throws IOException {
    int[] num = new int[3];
    File file = new File(filePath);
    if(!file.exists()) {
        System.out.println("文件不存在");
        return num; //文件不存在
    }
    BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
    int codeLineNum=0;
    int noteLineNum=0;
    int blankLineNum=0;
    String fileLine;
    while ((fileLine=bufferedReader.readLine())!=null){
        fileLine = fileLine.trim();
        //计算注释行
        if(fileLine.startsWith("/") || fileLine.startsWith("*")){
            noteLineNum++;
        }
        //计算空行
        else if(fileLine.trim().isEmpty() || fileLine.trim().length()==1){
            blankLineNum++;
        }
        //计算代码行
        else {
            codeLineNum++;
        }
    }
    bufferedReader.close();
    num[0] = codeLineNum;
    num[1] = noteLineNum;
    num[2] = blankLineNum;
    return num;
}
  • 高级功能部分核心代码

@FXML
public void open(ActionEvent actionEvent) throws IOException {
    File file = OpenUtil.chooseFile();
    long start = System.currentTimeMillis();
    if(file==null){
        warn.setText("你没有打开任何文件噢~");
        return;
    }else{
        path.setText(file.getAbsolutePath());
        int[] num;


        num = WordCount.wc("-c", file.getAbsolutePath());
        charNum.setText(String.valueOf(num[0]));
        num = WordCount.wc("-w", file.getAbsolutePath());
        wordNum.setText(String.valueOf(num[0]));
        num = WordCount.wc("-l", file.getAbsolutePath());
        lineNum.setText(String.valueOf(num[0]));


        num = ProWordCount.proCount(file.getAbsolutePath());
        codeNum.setText(String.valueOf(num[0]));
        noteNum.setText(String.valueOf(num[1]));
        blankNum.setText(String.valueOf(num[2]));
    }
    long runTime = TimeUtil.getRunTime(start);
    runtime.setText(runTime +"ms");
}

1.5 WC项目测试

测试文件:

空文件

只有一个字符的文件

只有一个词的文件

只有一行的文件

一个典型的源文件

 

空文件测试

 

 

 

单字符文件测试

单个词语文件测试

单行文件测试

典型源文件测试

package com.demo;
import java.io.*;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class WordCounter {
    public static void main(String[] args) throws IOException {
        /*
        Scanner scan = new Scanner(System.in);
        String model = "";
        String filePath = "";
        WordCounter.wc(model, filePath);
         */
        System.out.println(wc("-l", "C:\\Users\\15191\\Desktop\\imageTest\\testBrunch\\test\\C_language_Class2_1_utf8.txt"));
}

 

 

 

 

 

 

 

图形界面程序测试

 

2.1 项目小结

  1. 在实际写代码时需要花费较多的时间去规划每个模块之间的关系,但是还是没有做好;
  2. 在学习javafx的过程中花费了较多的时间;
  3. 在将项目打包成.exe过程中也遇到了许多小问题;
  4. 需要加强编程的练习。

猜你喜欢

转载自www.cnblogs.com/yozyyyqls/p/12554092.html