软件工程作业 - 实现WC功能(java)

项目地址:https://github.com/yogurt1998/WordCount

要求

  • 基本要求
    • -c 统计文件字符数(实现)
    • -w 统计文件单词数(实现)
    • -l 统计文件行数(实现)
  • 扩展功能
    • 递归处理目录下符合条件的文件。(实现)
    • 返回更复杂的数据(代码行 / 空行 / 注释行)(实现)
  • 高级功能
    • 实现图形化界面(未实现)

PSP

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

设计

main.java

主函数:一个循环获取输入命令并分隔出指令和文件路径。
统计函数:通过IO流获取文件内容并统计字符数、行数、单词数等。
文件判断函数:判断是否为文件夹或者文件以实现递归处理功能

AFile.java

代表着字符数等六个属性。

代码

main()函数

public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		
		do {
			String filename = null;
			String bString = null;
			System.out.println("请输入命令(格式:[parameter] [file_name])");
			
			while (true) {
				Scanner scanner = new Scanner(System.in); // 获取键盘输入
				
				if (scanner.hasNext()) {
					bString = scanner.next();
				}
				
				if (bString.equals("-c") || bString.equals("-w")
						|| bString.equals("-l") || bString.equals("-s")
						|| bString.equals("-a")) {
					if (scanner.hasNextLine()) {
						filename = scanner.next();
					}
					break;
				} else {
					System.out.println("错误!请重新输入!");
				}
			}
			
				String filepath = "D:\\test\\" + filename; // 在绝对路径中打开
				
				File file = new File(filepath);
				if (!file.exists()) {
					System.out.println("文件不存在");
					continue;
				}
				
				AFile aFile = new AFile();
				aFile = findFiles(filepath);
				
				if (bString.equals("-c"))
					System.out.println("字符数为" + aFile.charNumb);
				else if (bString.equals("-w"))
					System.out.println("单词数为" + aFile.wordNumb);
				else if (bString.equals("-l"))
					System.out.println("行数为" + aFile.lineNumb);
				else if (bString.equals("-a"))
					System.out.println("空行数为:" + aFile.empleLine 
							+ " 代码行数为:" + aFile.codeLine + " 注释行数为:" + aFile.nodeLine);
			
		} while(true);
		
	}

findFiles()函数:通过递归处理文件

private static AFile findFiles(String file_path) {

		File file = new File(file_path);
		AFile aFile = new AFile();
		
		if (file.isDirectory()) { // 判断为文件夹
			File[] files = file.listFiles(); // 获取文件列表
			if (files == null) {
				System.err.println("找不到");
			} else if (files.length == 0) {
				System.out.println("目录为空");
			} else {
				for (File f : files) { // 循环处理文件
					if (f.isDirectory()) // 判断为文件夹
						findFiles(f.getPath());
					else if (f.isFile()) { // 判断为文件
						System.out.println("文件名为:" + f.getName() + "\n字符数为" + getCount(f.getPath()).charNumb +
								"\n单词数为" + getCount(f.getPath()).wordNumb +
								"\n行数为" + getCount(f.getPath()).lineNumb + 
								"\n空行数为:" + getCount(f.getPath()).empleLine +
								"\n代码行数为:" + getCount(f.getPath()).codeLine +
								"\n注释行数为:" + getCount(f.getPath()).nodeLine);
					}
				}
			}
		} else if (file.isFile() && file.exists()) { // 判断为文件
			aFile = getCount(file.getPath());
		}
		
		return aFile;
	}

getCount()函数:通过BufferedReader获取文件内容并判断

private static AFile getCount(String filepath) {
		AFile aFile = new AFile();
		try {
			BufferedReader brin = new BufferedReader(new FileReader(filepath));
			String s;
			int state = 0; // 判断是否在单词内
			
			// 使用正则表达式判断注释行
			String regxNodeBegin = "(\\S?)\\s*/\\*.*";
			String regxNodeEnd = "(.*\\*/\\s*)\\S?";
			String regxNode = "(\\s*)(\\S?)(//+).*";
			
			while ((s = brin.readLine()) != null) {
				++ aFile.lineNumb;
				int countLetter = 0; // 判断非空格字符数量
				
				for (int i = 0; i < s.length(); i++) {
					++aFile.charNumb;
					Character c = s.charAt(i);
					++countLetter;
					if (c == ' ' || c == '\n' || c == '\t') {
						state = 0;
						--countLetter;
					}
					else if (state == 0) {
						state = 1;
						++aFile.wordNumb;
					}
				}
				
				if (s.matches(regxNodeBegin) || s.matches(regxNodeEnd)
						|| s.matches(regxNode))
					++aFile.nodeLine;
				else if (countLetter > 1) // 如果非空格字符数多于1
					++aFile.codeLine;
				else 
					++aFile.empleLine;
			}
		} catch (IOException e) {
			// TODO: handle exception
			System.out.println(e.getMessage());
		}
		
		return aFile;
	}

测试运行

测试文件:

测试结果:

总结

  1. 根据在软件工程课堂上得到的知识进行分析,但没有细心分析导致递归功能一开始写错。
  2. 程序的思路一开始并不是很清晰导致后面很多修改以及代码繁杂。
  3. 学习了Git和GitHub的使用以及exe4j的使用。
  4. 对程序设计很不熟悉需要更多的练习。
posted @ 2018-09-13 16:05  nuliba  阅读(210)  评论(0编辑  收藏  举报