wordcount java分析_Word Count (Java)

WordCount --java语言实现

由于GitHub网速问题(我在医院,没有wifi,只能开热点,上github速度过慢,难以将项目push到github上,因此,我的项目托管到了码云上)

gitee地址:!()[https://gitee.com/wangyuyong123/wordcloud]

1. 项目要求

1.1 题目描述

Word Count

实现一个简单而完整的软件工具(源程序特征统计程序)。

进行单元测试、回归测试、效能测试,在实现上述程序的过程中使用相关的工具。

进行个人软件过程(PSP)的实践,逐步记录自己在每个软件工程环节花费的时间。

1.2 功能列表

基本功能列表:

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

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

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

扩展功能:

-s 递归处理目录下符合条件的文件。

-a 返回更复杂的数据(代码行 / 空行 / 注释行)。

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

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

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

} //注释

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

高级功能:

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

需求举例:

wc.exe -s -a *.c

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

2. PSP

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

20

20

· Estimate

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

350

312

Development

开发

290

252

· Analysis

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

80

60

· Design Spec

· 生成设计文档

30

20

· Design Review

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

20

15

· Coding Standard

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

20

20

· Design

· 具体设计

30

32

· Coding

· 具体编码

50

55

· Code Review

· 代码复审

30

25

· Test

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

30

25

Reporting

报告

60

60

· Test Report

· 测试报告

20

20

· Size Measurement

· 计算工作量

20

20

· Postmortem & Process Improvement Plan

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

20

20

合计

370

332

3.关键代码与设计说明

3.1 总体设计

f2ca9000ca937bf53ec227260685b818.png

读入文件模块为ReadFileCls类实现

计数模块为WordCount类实现

程序启动后,程序将根据用户输入的参数判断是否合法,如果合法,将调用ReadFileCls类读入相应的文件,将文件存入内存后,只需要调用ReadFileCls的getContent方法即可获取文件内容的字符串,接着将文件内容的字符串传入WordCount类构成新的对象,根据用户输入的不同参数,调用wordcount不同的方法可以获得相应的结果(如,用户输入-c,则调用wordcount对象的getContentLength方法获取文件的字符数量)。

主函数的main方法如下:

import java.util.List;

public class Main {

public static ReadFileCls read;

public static WordCount wordCount;

public static void main(String[] args) {

if (args.length >= 3) {

int i = 0;

if (args[i].equals("-a") || args[++i].equals("-a")) {

int j = 1 - i;

if (args[j].equals("-c")) {

try {

operateAllFile(args[2], new Do() {

@Override

public void doSomething(String fileName, WordCount wordCount) {

System.out.println(fileName + "的字符数为:" + wordCount.getContentLength());

}

});

}catch (Exception e) {

showNoFile();

}

}else if (args[j].equals("-w")) {

try {

operateAllFile(args[3], new Do() {

@Override

public void doSomething(String fileName, WordCount wordCount) {

System.out.println(fileName + "的单词数为:" + wordCount.getWordCount());

}

});

}catch (Exception e) {

showNoFile();

}

}else if (args[j].equals("-l")) {

try {

operateAllFile(args[2], new Do() {

@Override

public void doSomething(String fileName, WordCount wordCount) {

System.out.println(fileName + "的行数为:" + wordCount.getContentLine());

}

});

}catch (Exception e) {

showNoFile();

}

}else {

showError();

}

}else {

showError();

}

} else if (args.length >= 2) {

if (args[0].equals("-c")) {

try {

init(args[1]);

System.out.println(args[1] + "字符数为:" + wordCount.getContentLength());

}catch (Exception e) {

showNoFile();

}

}else if (args[0].equals("-w")) {

try {

init(args[1]);

System.out.println(args[1] + "单词数:" + wordCount.getWordCount());

}catch (Exception e) {

showNoFile();

}

}else if (args[0].equals("-l")) {

try {

init(args[1]);

System.out.println(args[1] + "行数:" + wordCount.getContentLine());

}catch (Exception e) {

showNoFile();

}

}else {

showError();

}

} else {

showError();

}

}

public static void init(String filePath) throws Exception{

read = new ReadFileCls(filePath);

wordCount = new WordCount(read.getContent());

}

public static void showError() {

System.out.println("参数不规范");

}

public static void showNoFile() {

System.out.println("没有找到该文件");

}

public static void operateAllFile(String directory, Do operator)throws Exception{

read = new ReadFileCls(directory,true);

List fileContents = read.getAllContent();

List fileName = read.getAllFileName();

for (int i = 0; i < fileContents.size(); i++) {

wordCount = new WordCount(fileContents.get(i));

if (operator != null) {

operator.doSomething(fileName.get(i),wordCount);

}

}

}

}

3.2 ReadFileCls类的设计

该类有两个构造方法,第一个构造方法只带一个参数,传入文件名,之后调用getContent即可获取该文件内容的字符串(String),该类会将此字符串保留起来,如果下次再次调用,则直接将该字符串返回,无需在读取文件。第二个构造方法带两个参数,第一个是一个文件夹名称,第二个是布尔变量,表示是否递归处理该文件夹,使用该构造函数构造对象后,调用getAllContent方法,可以获取该目录夹下所有文件的内容,并返回一个字符串数组。

该类中,对文件的读写操作流程如下:

625d49c67ec69232627f6f1e99023573.png

该类具体代码如下:

import java.io.*;

import java.util.ArrayList;

import java.util.List;

public class ReadFileCls {

private File file;

private boolean isAll;

private String content;

public ReadFileCls(String filePath) {

this.file = new File(filePath);

}

public ReadFileCls(String filePath, boolean isAll) {

this.file = new File(filePath);

this.isAll = isAll;

}

/**

* 如果是文件夹,则递归获取文件夹内的所有内容

* 如果是文件,则获取该文件的内容

* @return 字符串数组

* @throws Exception 若该文件不存在,则抛出异常。

*/

public List getAllContent() throws Exception{

List allContent = new ArrayList<>();

if (isAll) {

if (file.exists()) {

if (file.isFile()) {

allContent.add(getContent());

}else {

File[] fileSon = file.listFiles();

if (fileSon != null) {

for (int i = 0; i < fileSon.length; i++) {

List temp = new ReadFileCls(fileSon[i].getAbsolutePath(), true).getAllContent();

allContent.addAll(temp);

}

}

}

}else {

throw new FileNotFoundException("没有此文件");

}

}else {

allContent.add(getContent());

}

return allContent;

}

/**

* 如果是文件夹,则递归获取文件夹内的文件的名字

* 如果是文件,则获取该文件的名字

* @return 字符串数组

* @throws Exception 若该文件不存在,则抛出异常。

*/

public List getAllFileName() throws Exception{

List allFileName = new ArrayList<>();

if (isAll) {

if (file.exists()) {

if (file.isFile()) {

allFileName.add(file.getName());

}else {

File[] fileSon = file.listFiles();

if (fileSon != null) {

for (int i = 0; i < fileSon.length; i++) {

List temp = new ReadFileCls(fileSon[i].getAbsolutePath(), true).getAllFileName();

allFileName.addAll(temp);

}

}

}

}else {

throw new FileNotFoundException("没有此文件");

}

}else {

allFileName.add(file.getName());

}

return allFileName;

}

/**

* 获取文件内容

* @return String 文件内容(若返回值为null,说明文件中没有内容)

* @throws Exception 若该文件不存在,则抛出异常

*/

public String getContent() throws Exception{

BufferedReader reader = null;

StringBuilder builder = new StringBuilder();

try {

reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));

String temp = null;

while ((temp = reader.readLine()) != null) {

builder.append(temp + "\n");

}

content = builder.toString();

} catch (FileNotFoundException e) {

e.printStackTrace();

throw e;

} finally {

if (reader != null) {

reader.close();

}

}

return content;

}

}

3.3 wordcount类的设计

wordcount类代码如下:

import java.util.List;

/**

* 获取字符串的各种信息

*/

public class WordCount {

private String content;

/**

* 所有行

*/

private int allLine = -1;

/**

* 空格

*/

private int space = -1;

/**

* 空行

*/

private int spaceLine = -1;

/**

* 代码行

*/

private int codeLine = -1;

/**

* 注释行

*/

private int NoteLine = -1;

private static final String ILLEGAL_CHARACTERS_REX = "[^a-zA-Z]";

private static final String BLANK_REX = " +";

private static final String NOTE_REX = "((//.*\\n)|(/\\*[.\\n]*\\*/))";

public WordCount(String content) {

this.content = content;

}

/**

* 获取字符串字符的数量

* @return 数量

*/

public int getContentLength() {

if (content != null) {

return content.length();

}else {

return 0;

}

}

/**

* 获取内容的行数

* @return 行数

*/

public int getContentLine() {

if (allLine == -1) {

if (content != null) {

String[] lines = content.split("\n");

if (lines.length == 1 && lines[0].equals("")) {

allLine = 0;

return allLine;

}

allLine = lines.length;

return allLine;

} else {

allLine = 0;

return allLine;

}

}else {

return allLine;

}

}

/**

* 获取空行

* @return 空行数量

*/

public int getSpaceLine() {

if (spaceLine == -1) {

if (content != null) {

int num = 0;

String[] fileLinse = content.split("\n");

for (int i = 0; i < fileLinse.length; i++) {

if (fileLinse[i].equals("")) {

num++;

}

}

spaceLine = num;

return spaceLine;

}else {

spaceLine = 0;

return spaceLine;

}

}else {

return spaceLine;

}

}

/**

* 获取注释行

* @return 注释行行数

*/

public int getNoteLine() {

List notes = new RexUtil(NOTE_REX,content).getRexString();

int lines = 0;

for (int i = 0; i < notes.size(); i++) {

String note = notes.get(i);

System.out.println(note);

if (note != null) {

String[] tip = note.split("\n");

lines += tip.length;

}

}

return lines;

}

/**

* 获取单词数目

* @return 单词数目

*/

public int getWordCount() {

//用正则表达式去除非法字符

if (content != null) {

String temp = content.replaceAll(ILLEGAL_CHARACTERS_REX, " ");

String[] words = temp.split(BLANK_REX);

if (words.length == 1 && words[0].equals("")) {

return 0;

}

return words.length - 1;

}else {

return 0;

}

}

}

4.运行测试

将代码通过命令行编译后:

c587761adc7a5b4363403e4a06736ddc.png

创建测试文件test.c

8da4d00ce5057273b8fb31bbcec794a2.png

此时文件为空文件

在命令行输入分别输入

java Main -c test.c

java Main -w test.c

java Main -l test.c

结果如下:

1b4ab77b7c125e9924149ded60bfc6bc.png

向test.c中输入内容:

98839d40b937d4ec9a6e1d43ef947a07.png

测试结果:

53c43ec5813fdd35929c26d635d80661.png

递归处理测试:

创建test文件夹:

5e4915a17e0381bc5e2ad73d24669486.png

5f63c22dd6b10ff23292f02105e28a02.png

0567a2805bbc42c99cf011a80b94e5b0.png

empty.c内容为空,其他文件都有一定的内容

测试结果:

b8f4e578a655a6277855158eb2e6481f.png

5.项目总结

因为时间较赶,部分功能还未完成(相应的功能模块已经编写好了,但存在这一些bug还没来得及修复,因此并没有完成此功能)。

抽象能力有待提高,代码维护性有待提高。

期待下一次的项目。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值