軟體工程 wc-project(JAVA)

来源:https://www.cnblogs.com/luty/archive/2018/09/14/9647121.html
-Advertisement-
Play Games

Github項目鏈接 一、項目簡介 該項目是一個常見的工具,它能統計文本文件的字元數、單詞數和行數。這個項目要求寫一個命令行程式,模仿已有wc.exe 的功能,並加以擴充,實現一個統計程式,它能正確統計程式文件中的字元數、單詞數、行數,以及還具備其他擴展功能,並能夠快速地處理多個文件。 二、項目實現 ...


Github項目鏈接

一、項目簡介

        該項目是一個常見的工具,它能統計文本文件的字元數、單詞數和行數。這個項目要求寫一個命令行程式,模仿已有wc.exe 的功能,並加以擴充,實現一個統計程式,它能正確統計程式文件中的字元數、單詞數、行數,以及還具備其他擴展功能,並能夠快速地處理多個文件。

二、項目實現情況

    •基本功能

       • -c 返迴文件的字元數 (實現)

       • -w 返迴文件的詞的數目 (實現)

       • -l 返迴文件的行數 (實現)

   •擴展功能   

              •  -s 遞歸處理目錄下符合條件的文件(實現)

        • -a 返回更複雜的數據(代碼行/空行/註釋行)(實現)

        • 支持各種文件的通配符(*,?)(實現)

   •高級功能

       • 基本的Windows GUI 程式操作(未實現)

        • 支持通過圖形界面選取文件(未實現)

        • 支持通過圖形界面展現文件的信息(未實現)

三、PSP

PSP2.1

Personal Software Process Stages

預估耗時(分鐘)

實際耗時(分鐘)

Planning

計劃

 30

 42

· Estimate

· 估計這個任務需要多少時間

 30

 42

Development

開發

 720

 960

· Analysis

· 需求分析 (包括學習新技術)

 90

 102

· Design Spec

· 生成設計文檔

 20

25

· Design Review

· 設計覆審 (和同事審核設計文檔)

 10

 12

· Coding Standard

· 代碼規範 (為目前的開發制定合適的規範)

 10

13

· Design

· 具體設計

 60

 65

· Coding

· 具體編碼

 410

 422

· Code Review

· 代碼覆審

 60

 75

· Test

· 測試(自我測試,修改代碼,提交修改)

 60

 246

Reporting

報告

120

 136

· Test Report

· 測試報告

90

95

· Size Measurement

· 計算工作量

10

 5

· Postmortem & Process Improvement Plan

· 事後總結, 並提出過程改進計劃

 20

 36

合計

 

 870

 1138

四、解題思路

 1、本項目分為基本功能、擴展功能、高級功能。除了主類,將功能類基本分為一個基本功能類、三個擴展功能類(包括計算代碼行、空行、註釋行的類和遞歸查找的類和通配符處理的類,分別對應三個擴展功能要求)

 2、計算各種行或詞的方法大致思路為:首先讀入文件 -> 使用readLine()方法逐行讀取 -> 依據計算的對象不同編寫不同的計算方法

 3、遞歸處理:編寫find()方法不斷遞歸,查找文件如果是文件夾返回所有文件和文件夾的絕對路徑接著再遞歸查找。如是文件則加入列表裡,最後再將一個個列表裡的對象取出處理。

 4、通配符處理:將用戶輸入的所有*或?分別用.*和.?代替(正則表達式的任意字元),並使用pattern類對象存儲模式,遞歸查找符合條件的文件。

五、設計實現過程

功能簡易基本流程圖如下所示:

 

代碼結構圖如下所示,包括五個類(一個基本功能類,三個擴展功能類,一個properties類),一個類對應幾個方法。

六、關鍵代碼與註釋思路說明

-c 返迴文件的字元數

public void strNum(String p) {  //計算字元數的方法
           try {
            BufferedReader bw = new  BufferedReader(new FileReader(p)); //讀入文件
            while((c2=bw.readLine())!=null) {
                String k = c2.replace(" ","");  //將空格全部替換成空
                a2=a2+k.length(); //每讀一行,累計字元數   
                sx.setStrNum(a2);
            }
            System.out.println("該文件的字元數為:"+sx.getStrNum());
            bw.close();
        } catch (FileNotFoundException e) {
            System.out.println("無法找到指定文件");
        } catch (IOException e) {
            System.out.println("I/O錯誤");
        }
       }

 -w 返迴文件的詞的數目

public void wordNum(String p) {  //計算單詞數的方法
        try {
            BufferedReader bw = new  BufferedReader(new FileReader(p)); //讀入文件
             StringBuffer sb=new StringBuffer();
                while((c3=bw.readLine())!=null) {    //readline讀取到換行不算為null
                    if(c3.matches("")==false) {   //字元比較不能直接!=,如果讀取的行非空執行下麵語句
                    sb.append(c3+"\\s");    //將讀取到的內容追加在StringBuffer對象中,在結尾加上一個空白字元避免與下行的首部相連
                    }
                }
                c3=sb.toString();  //轉為字元串模式
                String[] strings=c3.split("[^\\w]");  //以非詞字元為分隔 將詞分開
               System.out.println("該文件單詞個數為:"+(strings.length-1));
               bw.close();
        } catch (FileNotFoundException e) {
            System.out.println("無法找到指定文件");
        } catch (IOException e) {
            System.out.println("I/O錯誤");
        }
        }

 -l 返迴文件的行數

public void lineNum(String p) {  //計算行數的方法
           try {
            BufferedReader bw = new  BufferedReader(new FileReader(p));//讀入文件
            while(bw.readLine()!= null) {  //當讀行不為空
                a1++;                      //行數加一
                sx.setLineNum(a1);
            }
            System.out.println("該文件的行數為:"+sx.getLineNum());
            bw.close();      //關閉流
        } catch (FileNotFoundException e) {   //捕獲錯誤1
            System.out.println("無法找到指定文件");
        } catch (IOException e) {         //捕獲錯誤2
            System.out.println("I/O錯誤");
        }
        }

  -s 遞歸處理目錄下符合條件的文件

public class extended_function_recursion { //擴展功能第二部分支持 -s遞歸處理目錄下符合條件的文件
    
    basic_function bf = new basic_function(); //創建基本功能類對象
    extended_function ef = new extended_function(); //創建擴展功能類第一部分對象
    
    public void recursion(String fileName, String filePath) {  //遞歸處理目錄下符合條件的文件
        List<String> l = new ArrayList<String>();
        find(new File(filePath),fileName,l);
        String path = null;
        if(l.size()>=1)path = l.get(0);  //提取文件路徑
        System.out.println("該目錄下符合要求的文件的絕對路徑為:"+path);
    }

    public static void find(File file,String fileName,List<String> l) {  
        if (file.isDirectory()) {    //如果是一個文件夾,返回true
            File[] f1 = file.listFiles();  //返回某個當前目錄下的所有文件和文件夾的絕對路徑,返回的是File數組
            for (File f : f1) {  
                find(f,fileName,l); //遞歸執行
            }  
        }else{
            if(file.getName().equals(fileName)){
                l.add(file.getAbsolutePath()); //獲取絕對路徑
            }
        }
    }
}

-a 返回更複雜的數據(代碼行 / 空行 / 註釋行)

計算代碼行部分:

public void codeline(String p) {  //計算代碼行方法,判斷代碼行標準:本行包括多於一個字元的代碼
           try {
            BufferedReader bw = new  BufferedReader(new FileReader(p));//讀入文件
            while( (e1=bw.readLine())!= null) {
                if(e1.length()>=2){  //若本行內容長度多於一個字元
                    j1++;
                }
                sx.setCodeLine(j1);
            }
            System.out.println("該文件的代碼行數為:"+sx.getCodeLine());
            bw.close();
        } catch (FileNotFoundException e) {
            System.out.println("無法找到指定文件");
        } catch (IOException e) {
            System.out.println("I/O錯誤");
        }
        }

-a 返回更複雜的數據(代碼行 / 空行 / 註釋行)

計算空行部分:

public void blankline(String p) {   //計算空行的方法,判斷空行標準:本行全部是空格或格式控制字元,如果包括代碼,則只有不超過一個可顯示的字元
        try {
            BufferedReader bw = new  BufferedReader(new FileReader(p));
            while( (e2=bw.readLine())!= null) {
                o = e2.matches("\\s+||\\S");   //e2不加雙引號!!,如果讀行內容匹配多個空白字元或只有一個非空白字元,空行加一
                if(o == true) {     //=是錯的!!
                    j2++;
                }
                sx.setBlankLine(j2);
            }
            System.out.println("該文件的空行數為:"+sx.getBlankLine());
            bw.close();
        } catch (FileNotFoundException e) {
            System.out.println("無法找到指定文件");
        } catch (IOException e) {
            System.out.println("I/O錯誤");
        }
        }

-a 返回更複雜的數據(代碼行 / 空行 / 註釋行)

計算註釋行部分:

public void commentline(String p) { //計算註釋行的方法,判斷註釋行標準:本行不是代碼行(包括多於一個字元的代碼),並且本行包括註釋,註釋前可有}
        try {
            BufferedReader bw = new  BufferedReader(new FileReader(p));
            while( (e3=bw.readLine())!= null) {
                if(e3.contains("//")) {  //如果本行有//
                    o = (e3.substring(0, e3.indexOf("//"))).matches("\\S{0,1}");//判斷//前如果為一個或零個字元則為註釋行
                    if(o == true) {
                        j3++;}
                }
                else if(e3.contains("/*")){  //同理
                    o = (e3.substring(0, e3.indexOf("/*"))).matches("\\S{0,1}");
                    if(o == true) {
                    j3++;}
                }
                else if(e3.contains("*/")){  //同理
                    o = (e3.substring(0, e3.indexOf("*/"))).matches("\\S{0,1}");
                    if(o == true) {
                    j3++;}
                }
                sx.setCommentLine(j3);
            }
            System.out.println("該文件的註釋行數為:"+sx.getCommentLine());
            bw.close();
        } catch (FileNotFoundException e) {
            System.out.println("無法找到指定文件");
        } catch (IOException e) {
            System.out.println("I/O錯誤");
        }
    }

支持各種文件的通配符(*,?)部分:

public class tong_pei {  //擴展功能第三部分,支持各種文件的通配符(*,?)
    public File[] getFiles(String dir,String s) {  //getFiles方法,返回File數組存取路徑
         File file = new File(dir);
         s = s.replace("*", ".*");//將*換為正則表達式的零次或多次的任意字元
         s = s.replace("?", ".?");//將?換為正則表達式的一次或沒有的任意字元
         Pattern p = Pattern.compile(s); //用compile()方法設置匹配模式
         ArrayList list = filePattern(file, p);//調用filePattern方法
         File[] rtn = new File[list.size()];
         list.toArray(rtn);
         return rtn;
       }
    
    public ArrayList filePattern(File file, Pattern p) {
         if (file == null) {  //如果文件為空返回空
           return null;
         }
         else if (file.isFile()) { //判斷該文件是否標準文件
           Matcher fMatcher = p.matcher(file.getName());
           if (fMatcher.matches()) {
             ArrayList list = new ArrayList();
             list.add(file);
             return list;
           }
         }
         else if (file.isDirectory()) { //判斷文件是否為文件夾
           File[] files = file.listFiles();
           if (files != null && files.length > 0) {
             ArrayList list = new ArrayList();
             for (int i = 0; i < files.length; i++) {
               ArrayList rlist = filePattern(files[i], p);
               if (rlist != null) {
                 list.addAll(rlist);
               }
             }
             return list;
           }
         }
         return null;
       }
}

properties類

public class properties { //Properties類
  int strNum=0;
  int wordNum=0;
  int lineNum=0;
  int codeLine=0;    //代碼行
  int blankLine=0;   //空行
  int commentLine=0; //註釋行
  
public int getCodeLine() {
    return codeLine;
}
public void setCodeLine(int codeLine) {
    this.codeLine = codeLine;
}
public int getBlankLine() {
    return blankLine;
}
public void setBlankLine(int blankLine) {
    this.blankLine = blankLine;
}
public int getCommentLine() {
    return commentLine;
}
public void setCommentLine(int commentLine) {
    this.commentLine = commentLine;
}
    public int getStrNum() {
      return strNum;
}
    public void setStrNum(int strNum) {
      this.strNum = strNum;
}
    public int getWordNum() {
      return wordNum;
}
    public void setWordNum(int wordNum) {
      this.wordNum = wordNum;
}
    public int getLineNum() {
      return lineNum;
}
    public void setLineNum(int lineNum) {
      this.lineNum = lineNum;
}
}

主類

import java.io.File;
import java.util.Scanner;

public class wc {
    public static void main(String[] args) {
        basic_function mts = new basic_function(); //以下四行創建功能類對象
        extended_function wtf = new extended_function();
        extended_function_recursion efr = new extended_function_recursion();
        tong_pei tp = new tong_pei();
        
        
        Scanner scan = new Scanner(System.in);//創建Scanner類對象
        if (scan.hasNext()) { //若有輸入
            String str1 = scan.nextLine();
            if((str1.substring(0,2)).equals("-l"))mts.lineNum(str1.substring(3,str1.length()));
            if((str1.substring(0,2)).equals("-c"))mts.strNum(str1.substring(3,str1.length()));
            if((str1.substring(0,2)).equals("-w"))mts.wordNum(str1.substring(3,str1.length()));
            if((str1.substring(0,2)).equals("-a")) {
                wtf.codeline(str1.substring(3,str1.length()));  //substring() 方法返回的子串包括 start 處的字元,但不包括 stop 處的字元
                wtf.blankline(str1.substring(3,str1.length()));
                wtf.commentline(str1.substring(3,str1.length()));
            }
            if((str1.substring(0,2)).equals("-s")) {       
                String arrays[] = str1.split(" ");
                File f[] = tp.getFiles(arrays[2],arrays[1]); //調用tong_pei類中getFiles()方法
                for(File ff:f) {
                    efr.recursion(ff.getName(),ff.getAbsolutePath());
                }            
            }
            if((str1.substring(0,4)).equals("-s-a")) {
                basic_function bf = new basic_function(); //創建基本功能類對象
                extended_function ef = new extended_function(); //創建擴展功能類第一部分對象
                String arrays[] = str1.split(" ");
                File f[] = tp.getFiles(arrays[2],arrays[1]); //調用tong_pei類中getFiles()方法

                for(File ff:f) {
                    efr.recursion(ff.getName(),ff.getAbsolutePath());
                    System.out.println("以下為遞歸處理目錄下符合條件的文件的屬性:");
                    bf.lineNum(ff.getAbsolutePath());  //以下為文件屬性
                    bf.strNum(ff.getAbsolutePath());
                    bf.wordNum(ff.getAbsolutePath());
                    ef.codeline(ff.getAbsolutePath());
                    ef.blankline(ff.getAbsolutePath());
                    ef.commentline(ff.getAbsolutePath());
                }             
            }
        scan.close(); //關閉流
        }
    }
}

七、測試運行結果

-c 返迴文件的字元數:

 

 -w 返迴文件的詞的數目:

-l 返迴文件的行數:

-a 返回更複雜的數據(代碼行 / 空行 / 註釋行):

 -s 遞歸處理目錄下符合條件(條件:用戶指定的文件)的文件:

 -s 遞歸

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • RPC調用 多個服務協同完成一次業務時,由於業務約束(如紅包不符合使用條件、賬戶餘額不足等)、系統故障(如網路或系統超時或中斷、資料庫約束不滿足等),都可能造成服務處理過程在任何一步無法繼續,使數據處於不一致的狀態。傳統的基於資料庫本地事務的解決方案只能保障單個服務的一次處理具備原子性、隔離性、一致 ...
  • 網址:https://github.com/3216005214/wc.exe wc項目要求 wc.exe 是一個常見的工具,它能統計文本文件的字元數、單詞數和行數。這個項目要求寫一個命令行程式,模仿已有wc.exe 的功能,並加以擴充,給出某程式設計語言源文件的字元數、單詞數和行數。 實現一個統計 ...
  • str.isnumeric(): True if 只包含數字;otherwise False。註意:此函數只能用於unicode string str.isdigit(): True if 只包含數字;otherwise False。 str.isalpha():True if 只包含字母;othe ...
  • java其實沒有二維數組的概念,平常實現的二維數組只是元素是一維數組的一維數組,而數組也是引用類型,繼承自Object類。數組是new出來的。這些性質也就導致arraycopy()二維數組時出現的問題。 1、首先對於一維數組,如果元素都是基礎類型(如int,double等),使用arraycopy( ...
  • 此題最早看到是在我還什麼都不會的去年的暑期集訓,是V8講的DP專題,我當時還跑去問這概率怎麼做。這道題要求的是二維最長不上升子序列,加上位置一維就成了三維偏序問題,也就是套用CDQ分治,對位置排序,然後對一維分治,對剩下的一維樹狀數組,類似的問題用樹狀數組套平衡樹也能解決,但似乎常數很大。然後這題的 ...
  • 本地remix-ide安裝教程 一 開始安裝前 準備以下軟體 vs2015(主要會用到vc++的工具以及Windows sdk ||vs2017沒試過,不過應該可以) vs下載安裝以及解壓地址: https://blog.csdn.net/guxiaonuan/article/details/737 ...
  • 問題:如下圖,在百度編輯器中插入視頻,視頻網址可以識別,但是提交內容後視頻卻顯示不了。 解決:這個問題主要是編輯器中會過濾一些html標簽,所以可以給標簽添加白名單。 修改 ueditor.config.js 文件: 修改: img: ['src', 'alt', 'title', 'width', ...
  • Idea Live Template總結 [TOC] live template是idea中提高效率的利器之一,以前看過一些教程,平時經常在使用,減少了我很多繁複的工作,但是沒有系統的去整理過,最近準備系統的整理下,主要是自己平時用到的和官方文檔的說明,如果有不正確的地方。 定義 : Live te ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...