軟工做業——WC.exe(Java實現)

WC我的項目博客

github項目傳送門:https://github.com/Lyuthia/myWC.exe.git

1、項目相關要求

       
wc.exe 是一個常見的工具,它能統計文本文件的字符數、單詞數和行數。這個項目要求寫一個命令行程序,模仿已有wc.exe 的功能,並加以擴充,給出某程序設計語言源文件的字符數、單詞數和行數。前端

       
實現一個統計程序,它能正確統計程序文件中的字符數、單詞數、行數,以及還具有其餘擴展功能,並可以快速地處理多個文件。c++

具體功能要求:

程序處理用戶需求的模式爲:git

wc.exe [parameter] [file_name]github

基本功能列表:

  • wc.exe -c file.c //返回文件 file.c 的字符數
  • wc.exe -w file.c //返回文件 file.c 的詞的數目
  • wc.exe -l file.c //返回文件 file.c 的行數

擴展功能:

  • -s 遞歸處理目錄下符合條件的文件。
  • -a 返回更復雜的數據(代碼行 / 空行 / 註釋行)。

高級功能:

  • -x 這個參數單獨使用。若是命令行有這個參數,則程序會顯示圖形界面,用戶能夠經過界面選取單個文件,程序就會顯示文件的字符數、行數等所有統計信息。

2、遇到的困難及解決方法

  • 困難描述:沒用Java作過文件輸入、命令行帶參數的程序
  • 作過哪些嘗試:網上搜索相關資源進行學習
  • 是否解決:是
  • 有何收穫:瞭解並實現了相關功能

3、設計程序流程

解題思路

1.主函數:輸入命令,判斷是否須要經過文件夾遞歸查詢知足條件的文件,再執行「遞歸查詢函數」或「文件導入函數」數組

2.操做函數:循環遍歷命令行,依次執行指令相應的下列統計函數函數

3.循環遞歸指定目錄查詢知足後綴條件的文件:經過File文件流依次導入該目錄下的文件及文件夾進入文件數組,當該數組不爲空時循環遍歷數組內容,若數組內容爲文件,則調用操做函數執行相應操做,若數組內容爲文件夾,則迭代調用當前遞歸查詢函數繼續查詢工具

4.文件導入函數:經過File文件流讀取相應文件,再調用操做函數執行指令的相應函數學習

5.字符統計函數:經過readLine函數循環讀取文件的每一行內容,循環遍歷每一行內容中的每個字符,判斷是否爲符合標準的字符,是則字符數加1,不然繼續判斷下一個字符是否符合要求,直到結束測試

6.詞數統計函數:經過readLine函數循環讀取文件的每一行內容,把每一行內容以空格切割成每一個單詞,再統計切割出來的單詞數編碼

7.行數統計函數:經過readLine函數循環讀取文件的每一行內容,而後行數循環加1,直到結束

8.特殊行統計函數:經過readLine函數循環讀取文件的每一行內容,判斷該行是否爲「空行」、「註釋行」、「代碼行」,是則相應變量加1,直到結束

設計實現過程

流程圖

4、關鍵代碼

項目目錄:

項目目錄

主函數代碼:

public static void main(String[] args) throws IOException
{
    while (true) {
        // 輸出面板
        System.out.println("\n----------------------3216005168 WC程序----------------------");
        System.out.println("|   |");
        System.out.println("|-c [文件路徑]  返回文件字符數  |");
        System.out.println("|-w [文件路徑]  返回文件詞的數目|");
        System.out.println("|-l [文件路徑]  返回文件行數|");
        System.out.println("|-s [文件夾路徑]  搜索文件名(須爲第1位) |");
        System.out.println("|-a [文件路徑]  統計代碼行/空行/註釋行  |");
        System.out.println("|   |");
        System.out.println("-------------------------------------------------------------");

        // 獲取輸入指令
        System.out.println("Please enter the command:");
        Scanner command = new Scanner(System.in);
        String arr[]= command.nextLine().split("\\s");

        /* * 根據命令 執行操做 * */
        int len = arr.length;
        if(arr[0].equals("-s"))
            searchFile(arr);
        else
            operation(len,0,arr,arr[arr.length-1]);
    }
}

操做函數代碼:

private static void operation(int len,int start,String[] arr,String fileName) throws IOException
{
    for(int i=start;i<len-1;i++) {
        switch (arr[i]) {
            //指定文件下字符數、單詞數、行數、特殊行數
            case "-c":
            case "-w":
            case "-l":
            case "-a":
                searchByFileName(fileName,arr[i]);break;
            default:
                System.out.println("指令輸入錯誤!");
                break;
        }
    }
}

邏輯函數代碼:

1.基本功能整合

/* * 計算字符數的函數 * */
    private static void countChar(BufferedReader fileContent) throws IOException
    {
        int c = 0;//字符數
        String lineContent = null;
        while ((lineContent = fileContent.readLine()) != null)
        {
            lineContent=lineContent.trim();
            //System.out.println(lineContent);
            for(int i=0;i<lineContent.length();i++) {
                char a = lineContent.charAt(i);
                if(a!=' '&&a!='\n'&&a!='\t'&&a!=','&&a!='.'&&a!='!'&&a!=';'&&a!='=')
                    c++;
            }
        }
        System.out.println("字符數:" + c);
    }

    /* * 計算詞的數目的函數 * */
    private static void countWords(BufferedReader fileContent) throws IOException
    {
        int w = 0;//詞數
        String lineContent = null;
        while ((lineContent = fileContent.readLine()) != null)
        {
            lineContent=lineContent.trim();
            //System.out.println(lineContent);
            if(!lineContent.matches("^ *$"))
                w+=lineContent.replaceAll(" +"," ").split(" ").length;
        }
        System.out.println("詞數:" + w);
    }

    /* * 行的數目 * */
    private static void countLines(BufferedReader fileContent) throws IOException
    {
        int l = 0;//行數
        String lineContent = null;
        while ((lineContent = fileContent.readLine()) != null)
        {
            lineContent=lineContent.trim();
            //System.out.println(lineContent);
            l++;
        }
        System.out.println("行數:" + l);
    }

    /* * 特殊行的數目:代碼行數、空行數、註釋行數 * */
    private static void countSpecialRows(BufferedReader fileContent) throws IOException
    {
        int blankLine = 0;//空行數
        int codeLine = 0;//代碼行數
        int annotatedLine = 0;//註釋行數
        Boolean comment = false;

        String lineContent = null;

        while ((lineContent = fileContent.readLine()) != null)
        {
            lineContent=lineContent.trim();
            //System.out.println(lineContent);

            if (lineContent.matches("^[\\s&&[^\\n]]*$")||lineContent.length()==1) {
                blankLine++;
            } else if (lineContent.startsWith("/*") && !lineContent.endsWith("*/")) {
                annotatedLine++;
                comment = true;
            } else if (comment.equals(true)) {
                annotatedLine++;
                if (lineContent.endsWith("*/")) {
                    comment = false;
                }
            } else if (lineContent.startsWith("//")) {
                annotatedLine++;
            } else {
                codeLine++;
            }
        }
        //System.out.println("代碼行數:" + codeLine + " 空行數:" + blankLine + " 註釋行數:" + annotatedLine);
        System.out.println( codeLine + " / " + blankLine + " / " + annotatedLine);
    }

    /* * 查找指定文件 * */
    private static void searchByFileName(String fileName,String command) throws IOException
    {
        try {
            File file = new File(fileName);
            if (file.isFile() && file.exists()) {
                //從文件地址中讀取內容到程序中
                String encoding = "GBK";
                InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
                BufferedReader fileContent = new BufferedReader(read);

                switch (command) {
                    case "-c"://字符數
                        countChar(fileContent);break;
                    case "-w"://單詞數
                        countWords(fileContent);break;
                    case "-l"://行數
                        countLines(fileContent);break;
                    case "-a"://特殊行數
                        countSpecialRows(fileContent);break;
                    default:
                        System.out.println("\n********  指令輸入錯誤  **********");break;
                }

                read.close();
            } else {
                System.out.println("找不到指定的文件!");
            }
        } catch (Exception e) {
            System.out.println("讀取文件內容操做出錯");
            e.printStackTrace();
        }
    }

2.拓展功能

/* * 遞歸 獲取 指定目錄下 指定後綴 的 文件 * */
    private static void searchFile(String[] arr) throws IOException
    {
        //String fileDir = arr[arr.length-1];
        //String fileFilter = ".cpp";
        String fileDir = arr[arr.length-2];
        String fileFilter = arr[arr.length-1];

        List<File> fileList = new ArrayList<File>();
        File file = new File(fileDir);// 指定查找目錄
        File[] files = file.listFiles();// 獲取目錄下的全部文件或文件夾
        if (files == null) {// 若是目錄爲空,直接退出
            return;
        }
        // 遍歷files中的全部文件
        for (File f : files) {
            if (f.isFile()&&f.getName().endsWith(fileFilter)) {
                fileList.add(f);
                System.out.println(f.getName());
            } else if (f.isDirectory()) {
                arr[arr.length-2] = f.getAbsolutePath();
                System.out.println(f.getAbsolutePath());
                searchFile(arr);
            }
        }
        for (File f1 : fileList) {
            //operation(arr.length,1,arr,f1.getAbsolutePath());
            operation(arr.length-1,1,arr,f1.getAbsolutePath());
            //System.out.println(f1.getAbsolutePath());
        }
    }

5、測試運行

1.測試目錄/測試文件

測試目錄/測試文件

2.程序啓動:

程序啓動

3.基本功能:

基本功能

4.遞歸查詢文件

遞歸查詢文件

遞歸查詢2

5.統計代碼行、註釋行、空行

特殊行數

6.代碼覆蓋率

覆蓋率

6、PSP

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 30 45
· Estimate · 估計這個任務須要多少時間 · 30 · 45
Development 開發 780 645
· Analysis · 需求分析 (包括學習新技術) · 120 · 150
· Design Spec · 生成設計文檔 · 30 · 40
· Design Review · 設計複審 (和同事審覈設計文檔) · 30 · 30
· Coding Standard · 代碼規範 (爲目前的開發制定合適的規範) · 60 · 45
· Design · 具體設計 · 120 · 90
· Coding · 具體編碼 · 240 · 200
· Code Review · 代碼複審 · 60 · 30
· Test · 測試(自我測試,修改代碼,提交修改) · 120 · 60
Reporting 報告 120 105
· Test Report · 測試報告 · 60 · 45
· Size Measurement · 計算工做量 · 30 · 30
· Postmortem & Process Improvement Plan · 過後總結, 並提出過程改進計劃 · 30 · 30
合計 930 795

7、項目小結

       
首先,由於本身是前端方向的,對於Java的學習也只是停留在學校教學階段,因此在開發這個我的項目以前,從新回顧了一下Java的知識,也充分意識到本身對於Java語言的事件流的不瞭解,同時也學會了從0到1實現一個程序,從預估、設計、編碼、開發、測試、文檔等流程中鍛鍊本身。

        其次,在做業中使用了博客的方法來提交做業,對於一直想要搭建博客寫博文卻一直沒有實現的本身無疑是極好的,既能培養本身寫博客的習慣,又能提高本身的實踐能力。

相關文章
相關標籤/搜索