1. 程式人生 > >WordCount-拓展功能

WordCount-拓展功能

getpath 狀態 添加 單詞 http codec 互換 結對編程 由於

申明

  • 合作者:201631062407,201631062306
  • 代碼地址:https://gitee.com/hhhhhhh2/WordCount
  • 本次作業的鏈接地址:https://edu.cnblogs.com/campus/xnsy/2018Systemanalysisanddesign/homework/2188

正文

1. PSP表格

PSP2.1 PSP階段 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 5 1
· Estimate · 估計這個任務需要多少時間 5 1
Development 開發 152 243
· Analysis · 需求分析 (包括學習新技術) 2 10
· Design Spec · 生成設計文檔 0 0
· Design Review · 設計復審 (和同事審核設計文檔) 0 0
· Coding · 代碼規範 (為目前的開發制定合適的規範) 10 3
· Code Review · 具體設計 20 20
· Test · 具體編碼 120 210
Reporting · 代碼復審 65 30
· Test Report 報告 30 40
· Size Measurement · 測試報告 30 10
· Postmortem & Process · 計算工作量 5 10
Improvement Plan · 事後總結, 並提出過程改進計劃 10 120
合計 232 394
  • 小總結:

    這次由於已經做過PSP評估,有了一定經驗,估計值相較於上一次有了進步。這次的主要時間出入任然是具體編碼時間上的估計錯誤。當我一開始看題目要求的時候,認為實現擴展功能並不復雜,能夠很快實現。但是當我真正敲代碼的時候,我發現我在實現叠代文件夾目錄、用正則表達式來實現具體功能存在問題,所以查找資料花了較長的時間。

2. 互審代碼情況

我審查的模塊分別有:圖形化界面展示、停用詞表、通配符的實現。
以下是審查這些方法的測試結果:

2.1 圖形化界面

技術分享圖片

2.2 停用詞表

@Test
    public void testInStop() throws Exception{
        WordCount wordCount = new WordCount();
        String[] bufferL = null;    
        
        File dirr = new File("f:/stopList.txt");
        String[] bufferS = null;
        String Sline = null;
        BufferedReader bff = new BufferedReader(new FileReader(dirr));
        while((Sline = bff.readLine()) != null){
            //System.out.println("停用詞表中的單詞:" + Sline);
            bufferS = Sline.split(",| ");
        }//of while 

        File dir = new File("f:/a.c");
        BufferedReader br = new BufferedReader(new FileReader(dir));
        
        while((Sline = br.readLine()) != null)
        {
            //System.out.println("目標文件中讀取每一行內容:" + Sline);
            bufferL = Sline.split(",| ");
            for(int i = 0; i < bufferL.length; i++){
                boolean s = wordCount.inStop(bufferL[i], bufferS);
                System.out.println(s);
            }
        }
    }

技術分享圖片

2.3 通配符


@Test
    public void testGetFiles() {
        ArrayList<String> filenames = ExtendFunc.getFiles("F:/simulate");
        System.out.println(filenames);
        
        String[] test = "F:\\simulate\\*.c".split(", ");
        assertEquals(test, filenames.toArray());
    }

技術分享圖片

發現的問題:合作夥伴的代碼寫得很好,條理清晰,需求所要求的功能基本能夠實現。只是,
  1. 在寫入文件時,是在文件的尾部添加內容,不能夠在每次執行程序後,將文件原有的內容覆蓋。經過修改,每次執行後先將文件原有的內容清空,再添加程序執行後需要的內容。
  2. 通配符實現部分,當能夠實現通配符時,輸入的路徑為文件時報錯。
  3. 在程序運行時,把輸出的文件也當做讀取文件計算。

3. 設計過程

我們設計了一共有5個類,22個方法。他們的關系如圖所示:

技術分享圖片

關鍵函數的算法設計(流程圖),如圖所示:

技術分享圖片

4. 代碼說明

在結對項目中,我主要負責遞歸處理目錄下符合條件的文件、返回更復雜的數據(代碼行 / 空行 / 註釋行)和處理一般通配符的效果。代碼如下:

4.1 遞歸處理目錄下符合條件的文件、處理一般通配符


    
    /**
     * 遞歸獲取某路徑下的所有文件、文件夾,並返回包含該路徑下所有文件的數組
     */
    public static ArrayList<String> getFiles(String path) {
        ArrayList<String> fileNames = new ArrayList<String>();
        String[] paths = path.split("/");
        String filePath = "";       //該路徑下文件夾名
        for(int i=0; i<paths.length-1; i++){
            filePath += paths[i];
            filePath += "/";
        }
        File file = null;
        
        System.out.println(paths[paths.length-1].split("\\.").length);
        System.out.println(paths[paths.length-1]);
        
        //含通配符時
        if(paths[paths.length-1].contains("+") || paths[paths.length-1].contains("?")){
            file = new File(filePath);
            System.out.println("filePath:" + filePath);
            if(paths[paths.length-1].split("\\.").length<1){
                
                // 如果這個路徑是文件夾
                if (file.isDirectory())
                {
                    // 獲取路徑下的所有文件
                    File[] files = file.listFiles();
                    for (int i = 0; i < files.length; i++)
                    {
                        // 如果還是文件夾 遞歸獲取裏面的文件 文件夾
                        if (files[i].isDirectory()) 
                        {
                            getFiles(files[i].getPath());
                        }
                        else
                        {
                            fileNames.add(files[i].getPath());
                        }
                    }
                }
                else
                {
                    fileNames.add(file.getPath());
                }
            }else{
                String match_fileName = paths[paths.length-1];
                
                File[] files = file.listFiles();
                for (int i = 0; i < files.length; i++)
                {
                    //判斷是否符合含通配符的文件
                    if(files[i].getPath().matches(match_fileName)){
                        fileNames.add(files[i].getPath());
                    }
                }
            }
        }else{  //不含通配符時
            file = new File(path);
            // 如果這個路徑是文件夾
            if (file.isDirectory())
            {
                // 獲取路徑下的所有文件
                File[] files = file.listFiles();
                for (int i = 0; i < files.length; i++)
                {
                    // 如果還是文件夾 遞歸獲取裏面的文件 文件夾
                    if (files[i].isDirectory()) 
                    {
                        getFiles(files[i].getPath());
                    }
                    else
                    {
                        fileNames.add(files[i].getPath());
                    }
                }
            }
            else
            {
                fileNames.add(file.getPath());
            }
        }
        return fileNames;
    }

4.2 返回更復雜的數據(代碼行 / 空行 / 註釋行)

 public static String count_space_code_nodeNum(Count count, String path){
    
        BufferedReader fileReader = null;
        String str = "";

        int codeCount = 0;
        int spaceCount = 0;
        int nodeCount = 0;      
        count.spaceCount = 0;
        count.nodeCount = 0;
        count.codeCount = 0;
        
        try {
            fileReader = new BufferedReader(new FileReader(path));
            String line = null;
            boolean flagNode = false;
            while( (line = fileReader.readLine()) != null)
            {
                String regxNodeBegin = "\\s*/\\*.*";//空白字符任意多個、字符“/*”、任意字符、多個
                String regxNodeEnd = ".*\\*/\\s*";//任意字符、 零次或者多次、 出現字符“*/”、空白任意多個
                String regx = ".*//.*";//單行註釋
                String regxSpace = "\\s*";//空行
                
                
                //多行的單行註釋
                if( line.matches(regxNodeBegin) && line.matches(regxNodeEnd))
                {
                    nodeCount++;
                }
                else
                {
                    if(line.matches(regxNodeBegin))
                    {
                        nodeCount++;
                        flagNode = true;
                    }
                    else if(line.matches(regxNodeEnd))
                    {
                        nodeCount++;
                        flagNode = false;
                    }
                    else if(line.matches(regxSpace))
                    {
                        spaceCount++;
                    }
                    else if(line.matches(regx)){
                        nodeCount++;//單行註釋
                    }
                    else if(!flagNode)
                    {
                        codeCount++;
                    }else{
                        nodeCount++;
                    }
                }
            }
            
            count.spaceCount = spaceCount;
            count.codeCount = codeCount;
            count.nodeCount = nodeCount;
            
            str += "空行:" + spaceCount + "\r\n";
            str += "代碼行:" + codeCount + "\r\n";
            str += "註釋行:" + nodeCount + "\r\n";
            
        } catch (FileNotFoundException e) {
            str = "文件讀取有誤!";
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return str;
    }
    


5. 總結

在構建之法的結對項目的實踐經歷中,我感受頗多。通過結對編程我認識到了結對編程的好處:
  1. 促進參與項目的程序員自身的提高:一對程序員工作的時候,水平較低的一方會潛移默化地受水平略高的程序員影響,學到一些新的東西。而水平高的一方同樣因為不斷地把自己的想法說出來而整理了自己的思路。
  2. 促進大家對項目的熱愛:我們在編程中各自都會遇到問題,並相互改正。兩個人不斷的互換角色,以至於最後誰也記不清哪行代碼是誰敲的;整個項目的代碼是團隊共有,而不再是個人作品。
  3. 幫助加快項目的完成進度:一個人編程時,遇到問題可能想很久都不能夠解決,而隊友卻能很快的找出我們代碼中的錯誤並更正。
  4. 增加大家對編碼的積極性:如果單獨工作,在遇到困難的時候,並不是所有人都立刻積極地去解決問題,這時或許會上網和網友聊聊天,看看無關的網站等等,大半天的時間都浪費了。而結對編程有一種相互督促的作用,在一邊工作疲憊狀態不好使,另一邊會起一個鼓勵和激發鬥誌的作用。大家一起解決問題,完成工作,具有很高的效率和積極性。

    在這次結對編程中,我要感謝我隊友辛勤付出;我也通過這次的結對編程,感受到了1+1>2。

WordCount-拓展功能