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

该项目通过命令行接收参数,统计文件的字符数、单词数、行数,并具备处理目录下所有文件的能力,支持统计代码行、空行和注释行。项目使用Java编写,涉及IO流操作、递归算法及正则表达式。

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

要求

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

      PSP

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

      设计

      main.java

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

      AFile.java

      代表着字符数等六个属性。
      1489181-20180913153322155-1598359792.png

      代码

      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;
      }

    测试运行

    测试文件:
    1489181-20180913154915371-2133831421.png

测试结果:
1489181-20180913155230877-1459926887.png

总结

  1. 根据在软件工程课堂上得到的知识进行分析,但没有细心分析导致递归功能一开始写错。
  2. 程序的思路一开始并不是很清晰导致后面很多修改以及代码繁杂。
  3. 学习了Git和GitHub的使用以及exe4j的使用。
  4. 对程序设计很不熟悉需要更多的练习。

转载于:https://www.cnblogs.com/dwell/p/9641168.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值