1. 程式人生 > >小白のjava實現wc.exe功能

小白のjava實現wc.exe功能

cte string 目前 exc dsw != 獲取文件 讀取 界面

GitHub地址


項目完成情況

  基本功能列表(已實現)

    wc.exe -c file.c //返回文件 file.c 的字符數

    wc.exe -w file.c //返回文件 file.c 的詞的數目

    wc.exe -l file.c //返回文件 file.c 的行數

  擴展功能(已實現)

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

      空行:本行全部是空格或格式控制字符,如果包括代碼,則只有不超過一個可顯示的字符,例如“{”。

      代碼行:本行包括多於一個字符的代碼。

      註釋行:本行不是代碼行,並且本行包括註釋。一個有趣的例子是有些程序員會在單字符後面加註釋:

        } //註釋
      在這種情況下,這一行屬於註釋行。

      [file_name]: 文件或目錄名,可以處理一般通配符。

  高級功能(未實現)

    -x 參數。這個參數單獨使用。如果命令行有這個參數,則程序會顯示圖形界面,用戶可以通過界面選取單個文件,程序就會顯示文件的字符數、行數等全部統計信息。

    需求舉例:
      wc.exe -s -a *.c 返回當前目錄及子目錄中所有*.c 文件的代碼行數、空行數、註釋行數。

PSP2.1表格預估

技術分享圖片

解題思路

  用java實現wc.exe文件:實現3個基本功能,必須通過輸入流接收文件內容。實現“-s”擴展功能,則需要通過遞歸,將文件名存入字符串列表,之後循環輸出。實現“-a”擴展功能,我的思路是用readLine()方法將源文件一行一行接收,然後通過條件語句判斷;而判斷的順序是:先判斷是否是空行,再判斷是否為註釋行,除去這兩種,剩下的就都是代碼行了。

代碼說明

  統計字符數方法:countCharacter()

    filePath:文件路徑

    用BufferedReader中的read()方法讀取字符並進行判斷:是否為可以用鍵盤鍵入的字符【ASCII碼大於等於32,且不等於127(DEL)】,如果是,字符數加1。

1 public void countCharacter(String filePath) throws IOException {
2     int character=0;
3     BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"gb2312"));
4     int i;
5     while(-1!=(i=br.read()))
6         if(i>=32&&i!=127) character++;//只計入鍵盤輸入的字符
7     br.close();
8     System.out.println("字符數:"+character);
9 }

  統計行數方法:countLine()

    filePath:文件路徑

    用BufferedReader中的readLine()方法讀取每行字符,每讀取一行,行數加1。

1 public void countLine(String filePath) throws IOException {
2     int line=0;
3     BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"gb2312"));
4     while(null!=br.readLine()) line++;
5     br.close();
6     System.out.println("行數:"+line);
7 }

  統計單詞數方法:countWord()

    filePath:文件路徑

    用BufferedReader中的readLine()方法讀取一行字符並存入str中,然後用replaceAll()方法將字符串中,非字母、單引號(‘)、下劃線(_)、連接符(-)的字符替換成空格,再用split()分隔成字符串數組,統計數組中包含字母的字符串的數目即為該行字符的單詞數,循環該流程得出整個源文件的單詞數。

 1 public void countWord(String filePath) throws IOException {
 2     int word=0;
 3     BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"gb2312"));
 4     String str="";
 5     while(null!=(str=br.readLine())){
 6         str=str.replaceAll("[^A-Za-z‘_-]"," ");   //將不是字母、單引號、下劃線、連接符的字符替換成空格
 7         for(String s:str.split(" "))   //用空格分隔字符串
 8             if(Pattern.matches(".*[A-Za-z]+.*",s)) word++;  //字符串包含字母,就算是單詞
 9     }
10     br.close();
11     System.out.println("單詞數:"+word);
12 }

  統計代碼行、空行、註釋行:getCount()

    filePath:文件路徑

    用BufferedReader中的readLine()方法讀取每行字符並用replaceAll()方法,將非字母、斜杠(/)、星號(*)的字符都換成空字符,再存入字符串數組中。遍歷字符串數組判斷歸類為代碼行、空行、註釋行:空字符串即為空行;以雙斜杠(//)開頭,或(/*)開頭(*/)結尾之間的字符串都為註釋行;剩下的就是代碼行了。

 1 public void getCount(String filePath) throws IOException {
 2     int codeLine=0,blankLine=0,commentLine=0;
 3     BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"gb2312"));
 4     String str="";
 5     List<String> strs=new ArrayList<String>();
 6     boolean sign=false;
 7     while(null!=(str=br.readLine()))
 8         strs.add(str.replaceAll("[^A-Za-z/*]",""));
 9     for(int i=0;i<strs.size();i++){
10         //空行
11         if(strs.get(i).equals("")&&sign==false) blankLine++;
12         //單行註釋
13         else if(strs.get(i).startsWith("//")&&sign==false) commentLine++;
14         //多行註釋
15         else if(strs.get(i).startsWith("/*")||sign==true){
16             commentLine++;
17             sign=true;
18         } else if(strs.get(i).endsWith("*/")&&sign==true){
19             commentLine++;
20             sign=false;
21         }
22         //代碼行
23         else codeLine++;
24     }
25     System.out.println("代碼行:"+codeLine);
26     System.out.println("空行:"+blankLine);
27     System.out.println("註釋行:"+commentLine);
28     br.close();
29 }

  遞歸獲取目錄下符合條件的文件

    file:以文件夾路徑實例化的File實例

    paths:用於存文件路徑的字符串數組

    flag:要獲取的文件的格式

    返回結果:存有獲取文件的路徑的字符串數組

    遍歷file通過listFiles()方法提取出的File數組,用path接收File數組每個File元素的路徑。判斷路徑是否以文件格式flag結尾:是就加入字符串數組paths;否則就判斷路徑是否是目錄路徑,是就通過遞歸執行該方法。

 1 public List<String> getFiles(File file,List<String> paths,String flag) {
 2     File[] files=file.listFiles();
 3     if(null==files) return paths;
 4     for(File f:files){
 5         String path=f.getPath();
 6         if(path.endsWith(flag)) paths.add(path);
 7         if(f.isDirectory()) getFiles(f,paths,flag);
 8     }
 9     return paths;
10 }

測試運行

  a.java為空文件

技術分享圖片

  a.java為一個源文件

                a.java
1
/******************************************************* 2 Hello World 3 *******************************************************/ 4 public void main(String[] args) { 5 6 //HelloWorld.java 7 8 System.out.println("HelloWorld");//HelloWorld.java 9 }

技術分享圖片

  查找D盤下所有以.java結尾的文件

技術分享圖片

項目小結

  這是我第一次這麽系統地完成一個項目。以前都是讀完題目要求就直接敲代碼,並沒有去進行詳細地分析,也沒有計時。而現在能清楚地看到自己做一個項目所花的時間要比自己預估的時間要長,這點就必須改進,而且要學會更好地判斷預估自己的能力。

  而在測試過程中發現在遞歸查找文件的算法耗時較多,不過目前沒有較好的解決方案,期待日後能得以解決。

----------碼場小白,求輕噴T T----------

小白のjava實現wc.exe功能