1. 程式人生 > >第二周作業wordcount

第二周作業wordcount

根據 ces 功能需求 統計 buffere dev 得出 階段 exce

github項目鏈接https://github.com/liqia/WordCount

1.項目簡介

對程序設計語言源文件統計字符數、單詞數、行數,統計結果以指定格式輸出到默認文件中,以及其他擴展功能,並能夠快速地處理多個文件。

可執行程序命名為:wc.exe,該程序處理用戶需求的模式為:

wc.exe [parameter] [input_file_name]

存儲統計結果的文件默認為result.txt,放在與wc.exe相同的目錄下。

2.項目psp表格

PSP2.1表格

PSP2.1

PSP階段

預估耗時

(分鐘)

實際耗時

(分鐘)

Planning

計劃

60 100

· Estimate

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

兩天 一天半

Development

開發

一天 一天

· Analysis

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

180   240

· Design Spec

· 生成設計文檔

50   60

· Design Review

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

30 30

· Coding Standard

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

20 60

· Design

· 具體設計

100 120

· Coding

· 具體編碼

240 260

· Code Review

· 代碼復審

30 50

· Test

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

120 60

Reporting

報告

140 100

· Test Report

· 測試報告

50 30

· Size Measurement

· 計算工作量

40 60

· Postmortem & Process Improvement Plan

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

60 60

3.思路

首先要有對java文件處理的,因為要讀文件還要寫文件;

對字符進行統計,就要會一些正則表達式去處理這些字符串;

為了便於管理項目還要將項目推到GitHub上;

4.程序設計實現

(1)首先要對輸入的參數進行處理,得出要調用哪些功能模塊;

    為了滿足需求中的輸出順序,我使用一個特定數組a[參數的個數]來表示每一個可能出現的參數存在不存在,存在則在相應的位置置1,掃描完參數之後,就可以按照需求規定的順序進行處理了。詳情請看代碼

  代碼:

  

public static void main(String[] args) {
int[] canshu=new int[5];//0-4分別表示字符、單詞、行數、代碼行數/空行數/註釋行、遞歸處理 的參數存在不存在
String file = new String();
String outputFile = new String();
String stopListFile = new String();
int flag=0;
for(int i=0;i<args.length;i++) {
if (args[i].equals("-c")) canshu[0]=1;
else if (args[i].equals("-w")) canshu[1]=1;
else if (args[i].equals("-l")) canshu[2]=1;
else if (args[i].equals("-a")) canshu[3]=1;
else if (args[i].equals("-s")) canshu[4]=1;
else if (args[i].equals("-o"))
{
if (i==args.length-1) erro("參數不匹配");
if (Pattern.compile("\\w+\\.txt").matcher(args[i+1]).find())
{
outputFile=args[i+1];
i++;
}
else {
erro("輸出文件名不正確");
}
}
else if (args[i].equals("-e"))
{
if (i==args.length-1) erro("參數不匹配");
if (Pattern.compile("\\w+\\.txt").matcher(args[i+1]).find())
{
stopListFile=args[i+1];
i++;
}
else {
erro("參數不匹配");
}
}
else if (Pattern.compile("(\\w+|\\*)\\.\\w+").matcher(args[i]).find()) {
if (i==0) erro("輸入參數不正確");
flag=1;
file=args[i];
}
else {
erro("參數不匹配");
}
}
if (flag == 0) erro("參數不匹配");

execute(canshu,file,stopListFile,outputFile);
}

(2)按照功能需求編寫各個模塊

    將文件中的字符一次性讀到String中:

static public String retext(String fileName) {
if (fileName == null) {
return null;
}
InputStream is = null;
try {
is = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
erro("找不到指定文件");
}
String text = null;
try {
byte[] b = new byte[is.available()];//available函數將會獲取輸入流中字節總數
is.read(b);//根據前面獲得的字節總數,一次性讀出所有字節
text = new String(b);
is.close();
} catch (FileNotFoundException var5) {
var5.printStackTrace();
} catch (IOException var6) {
var6.printStackTrace();
}
return text;
}

統計單詞數,行數:
使用String類中的split函數用正則表達式匹配進行分割
String[] strings = text.split("\\.|,|\\s");

將結果寫入文件:
static public void output(String text, String outputFile) {
try {
FileOutputStream fos = new FileOutputStream(outputFile,true);//第二個參數Ture表示從文件末尾追加寫入
fos.write(text.getBytes());
fos.close();
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
停用詞表:
首先將詞表文件讀出,然後分割成各個詞,再進行單詞統計的時候判斷單詞時候是否再停用詞表中,以此決定計數與否

返回代碼行/空行/註釋行:

按行讀取文件,
判斷空行的時候就匹配正則表達式中的\s,以及是否是}單獨一行
判斷註釋的時候,對於“//”可以這樣寫正則表達式
\\s*//.*|\\}//.*}
對於“/**/”就需要再匹配到“/*”的時候置一個用於標記的flag為ture,之後的每一行都是註釋,直到匹配到“*/”並將flag置為0;
詳細代碼:

public class CountLine {
private int cntCode=0, cntNode=0, cntSpace=0;
private boolean flagNode = false;
public int[] reA(String fileName) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(fileName));
String line=null;
while((line = br.readLine()) != null)
pattern(line);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("註釋行: " + cntNode);
System.out.println("空行: " + cntSpace);
System.out.println("代碼行: " + cntCode);
System.out.println("總行: " + (cntNode+cntSpace+cntCode));
return new int[]{cntCode, cntSpace, cntNode};
}

private void pattern(String line) {
// TODO Auto-generated method stub
String regxNodeBegin = "\\s*/\\*.*";
String regxNodeEnd = ".*\\*/\\s*";
String regx = "\\s*//.*|\\}//.*}";
String regxSpace = "(\\s*)|(\\s*(\\{|\\})\\s*)";
int i=line.length();
if(line.matches(regxNodeBegin) && line.matches(regxNodeEnd)){
++cntNode;
return ;
}
if(line.matches(regxNodeBegin)){
++cntNode;
flagNode = true;
} else if(line.matches(regxNodeEnd)){
++cntNode;
flagNode = false;
} else if(line.matches(regxSpace)||line.equals("\uFEFF"))
++cntSpace;
else if(line.matches(regx))
++cntNode;
else if(flagNode)
++cntNode;
else ++cntCode;
}
}
5.測試設計過程
考慮到字符串為空的時候可能會有意想不到的bug 所以再測試過程中盡量的會去進行邊界測試。
        //測試函數retext
String text = WordCount.retext("src/momo/File.txt");
// String text1 = WordCount.retext(" ");
System.out.println(text);;
//測試函數reWord
int testReWord1 = WordCount.reWorld(null, null);
int testReWord2 = WordCount.reWorld(text, "whetu.txt");
//測試reCount函數
int testReCount = WordCount.reCount(null);
int testReCount1 = WordCount.reCount(text);
//測試reLine函數
int testReLine = WordCount.reLine(null);
int testReLine1 = WordCount.reLine(text);
//測試output函數
WordCount.output(null,"whetu.txt");
WordCount.output("123","whetu.txt");
6.參考文件鏈接
 java文件讀取的幾種方式https://www.cnblogs.com/hudie/p/5845187.html
java正則表達式http://www.runoob.com/java/java-regular-expressions.html
java中獲取文件夾或則文件路徑的方法https://www.cnblogs.com/tk55/p/6064160.html
idea如何打包jarhttps://jingyan.baidu.com/article/7e4409531fbf292fc1e2ef51.html

第二周作業wordcount