wc.exe 是一個常見的工具,它能統計文本文件的字符數、單詞數和行數。這個項目要求寫一個命令行程序,模仿已有wc.exe 的功能,並加以擴充,給出某程序設計語言源文件的字符數、單詞數和行數。前端
實現一個統計程序,它能正確統計程序文件中的字符數、單詞數、行數,以及還具有其餘擴展功能,並可以快速地處理多個文件。c++
程序處理用戶需求的模式爲:git
wc.exe [parameter] [file_name]github
1.主函數:輸入命令,判斷是否須要經過文件夾遞歸查詢知足條件的文件,再執行「遞歸查詢函數」或「文件導入函數」
數組
2.操做函數:循環遍歷命令行,依次執行指令相應的下列統計函數
函數
3.循環遞歸指定目錄查詢知足後綴條件的文件:經過File文件流依次導入該目錄下的文件及文件夾進入文件數組,當該數組不爲空時循環遍歷數組內容,若數組內容爲文件,則調用操做函數執行相應操做,若數組內容爲文件夾,則迭代調用當前遞歸查詢函數繼續查詢
工具
4.文件導入函數:經過File文件流讀取相應文件,再調用操做函數執行指令的相應函數
學習
5.字符統計函數:經過readLine函數循環讀取文件的每一行內容,循環遍歷每一行內容中的每個字符,判斷是否爲符合標準的字符,是則字符數加1,不然繼續判斷下一個字符是否符合要求,直到結束
測試
6.詞數統計函數:經過readLine函數循環讀取文件的每一行內容,把每一行內容以空格切割成每一個單詞,再統計切割出來的單詞數
編碼
7.行數統計函數:經過readLine函數循環讀取文件的每一行內容,而後行數循環加1,直到結束
8.特殊行統計函數:經過readLine函數循環讀取文件的每一行內容,判斷該行是否爲「空行」、「註釋行」、「代碼行」,是則相應變量加1,直到結束
項目目錄:
主函數代碼:
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()); } }
1.測試目錄/測試文件
2.程序啓動:
3.基本功能:
4.遞歸查詢文件
5.統計代碼行、註釋行、空行
6.代碼覆蓋率
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 |
首先,由於本身是前端方向的,對於Java的學習也只是停留在學校教學階段,因此在開發這個我的項目以前,從新回顧了一下Java的知識,也充分意識到本身對於Java語言的事件流的不瞭解,同時也學會了從0到1實現一個程序,從預估、設計、編碼、開發、測試、文檔等流程中鍛鍊本身。
其次,在做業中使用了博客的方法來提交做業,對於一直想要搭建博客寫博文卻一直沒有實現的本身無疑是極好的,既能培養本身寫博客的習慣,又能提高本身的實踐能力。