WC項目反思與總結
1. 項目需求說明
WordCount的需求可以概括為:對程序設計語言源文件統計字符數、單詞數、行數,統計結果以指定格式輸出到默認文件中,以及其他擴展功能,並能夠快速地處理多個文件。
可執行程序命名為:wc.exe,該程序處理用戶需求的模式為:
wc.exe [parameter] [input_file_name]
存儲統計結果的文件默認為result.txt,放在與wc.exe相同的目錄下。
1. 1 基本功能:
wc.exe -c file.c //返回文件 file.c 的字符數wc.exe -w file.c //返回文件 file.c 的單詞總數wc.exe -l file.c //返回文件 file.c 的總行數wc.exe -o outputFile.txt //將結果輸出到指定文件outputFile.txt
註意:
空格,水平制表符,換行符,均算字符。
由空格或逗號分割開的都視為單詞,且不做單詞的有效性校驗,例如:thi#,that視為用逗號隔開的2個單詞。
-c, -w, -l參數可以共用同一個輸入文件,形如:wc.exe –w –c file.c 。
-o 必須與文件名同時使用,且輸出文件必須緊跟在-o參數後面,不允許單獨使用-o參數。
舉例:
wc.exe –c file.c,則輸出結果保存在result.txt中,內容格式如下(註意大小寫):
file.c, 字符數: 50
wc.exe –w file.c,則輸出結果保存在result.txt中,內容格式如下(註意大小寫):
file.c, 單詞數: 30
wc.exe –l file.c,則輸出結果保存在result.txt中,內容格式如下(註意大小寫):
file.c, 行數: 10
wc.exe –l –c file.c,則統計file.c中的字符數和行數,輸出結果保存在result.txt中,內容格式如下:
file.c, 字符數: 50
file.c, 行數: 10
2. 編碼過程
Gitee項目
PSP表格
PSP2.1 | PSP階段 | 預估耗時(分鐘) | 實際耗時(分鐘) | |
Planning | 計劃 | 10 | 1 | |
· Estimate | · 估計這個任務需要多少時間 | 10 | 1 | |
Development | 開發 | 720 | 635 | |
· Analysis | · 需求分析 (包括學習新技術) | 10 | 5 | |
· Design Spec | · 生成設計文檔 | 30 | 40 | |
· Design Review | · 設計復審 (和同事審核設計文檔) | 10 | 0 | |
· Coding | · 代碼規範 (為目前的開發制定合適的規範) | 10 | 0 | |
· Code Review | · 具體設計 | 10 | 5 | |
· Test | · 具體編碼 | 610 | 540 | |
Reporting | · 代碼復審 | 10 | 5 | |
· Test Report | 報告 | 30 | 40 | |
· Size Measurement | · 測試報告 | 30 | 10 | |
· Postmortem & Process | · 計算工作量 | 10 | 0 | |
Improvement Plan | · 事後總結, 並提出過程改進計劃 | 10 | 5 | |
合計 | 770 | 656 |
2. 1 解題思路
剛拿到題目時,我先看了題目需求,並列出主要要實現的功能:
1. 讀取文件內容
2. 計算字符數
3. 計算單詞數
4. 計算行數
5. 向文件寫入內容
經過主要的功能分析後,我決定用我比較熟悉的java語言來完成這個題目。
其次,我分析了用java語言完成該題目主要需要運用的知識是:文件的IO流部分的知識。
於是我復習了我自己學習java IO字符流模塊的知識和筆記,相關筆記如下:
/*
------------| Reader 抽象類 輸入字符流的基類
-----------------------| FileReader 讀取文件的輸入字符流
FileReader的步驟:
1. 找到目標文件
2. 建立數據輸入字符流通道
3. 讀取數據
*/
package cn.itcast.charstream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class Demo1 {
public static void main(String[] args) throws IOException {
read1();
read2();
}
public static void read1() throws IOException {
File file = new File("E:/作業/Java/文件/b.txt");
FileReader fileReader = new FileReader(file);
int content = 0;
while((content = fileReader.read()) != -1){//每次讀一個字符
System.out.print((char)content);
}
fileReader.close();
}
public static void read2() throws IOException {
File file = new File("E:/作業/Java/文件/b.txt");
FileReader fileReader = new FileReader(file);
//建立緩沖字符數組
char[] buf = new char[1024];
int length = 0;
while((length = fileReader.read(buf)) != -1)
{
System.out.println(new String(buf, 0, length));
}
}
}
/*
--------------| Write 抽象類 輸出字符流的基類
--------------------------| FileWriter 向文件數據輸出數據的輸出字符流
FileWriter 的使用步驟:
1. 找到目標文件
2. 建立字符輸出流通道
3. 輸出數據
4. 關閉文件
註意:
1. filewriter底層維護了一個1024的字符數組,寫的數據先存在該數組中,當調用flush或close方法或填滿了數組才會保存到硬盤上。
2. new FileWriter(file); 如果目標文件不存在,會自動創建。
3. new FileWriter(file);默認先清空數據。如果要直接添加數據,使用FileWriter(File,true)。
*/
package cn.itcast.charstream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException {
write();
}
public static void write() throws IOException {
File file = new File("E:/作業/Java/文件/b.txt");
FileWriter fileWriter = new FileWriter(file);
String data = "今天很開心";
fileWriter.write(data);
fileWriter.close();
}
}
然後,我又思考發現,在計算單詞數的時候,可以通過正則表達式來截取字符串的方式計算單詞數量,
所有我又復習了正則表達式的相關用法,相關示例如下:
範圍詞
[abc] 出現的只能是abc其中的一個
[^abc] 出現的只能是除了abc 的一個任意字符
[a-z1-9&$] 出現的只能是兩頭字母包括在內的字符(即:a~z 或1~9 或&或$)
2. 2 程序設計實現過程
在實際編碼中,我使用了四個類,其類名和相關用途如下:
BaseCount:解析用戶輸入的命令行、調用JudgeOption類
相關方法:
wordCountMain()
BaseFunc:實現計算字符數、單詞書、行數這三個方法
相關方法:
count_charsNum(String path)
count_wordsNum(String path)
count_linesNum(String path)
JudgeOption:判斷用戶輸入參數,調用BaseFunc中對應的相關方法
相關方法:
judge(String arg, String readPath, String writePath)
WriteCount:把計算後的結果寫出到指定文件
相關方法:
writeCount(String str, String path)
initFile(String path):如果寫出的文件存在,將文件內容清空
2. 3 代碼說明
public class BaseFunc {
public static int count_charsNum(String path){
int count = 0;
try {
FileReader fileReader = new FileReader(path);
char[] buf = new char[1024];
int length = 0;
while( (length = fileReader.read(buf)) != -1){
count += length;
}
fileReader.close();
} catch (FileNotFoundException e) {
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
return count;
}
public static int count_wordsNum(String path) {
int count = 0;
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
while(br.read()!=-1)
{
String s = br.readLine();
for(int i=0; i<s.split("[^a-zA-Z]").length; i++){
if( !s.split("[^a-zA-Z]")[i].isEmpty()){
count ++;
}
}
}
br.close();
} catch (Exception e) {
System.out.println(e);
}
return count;
}
public static int count_linesNum(String path) {
int count = 0;
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
while(br.read()!=-1)
{
String s = br.readLine();
count++;
}
br.close();
} catch (Exception e) {
System.out.println(e);
}
return count;
}
}
public class JudgeOption {
public static void judge(String arg, String readPath, String writePath) {
int count = 0;
String str = "";
switch (arg) {
case "-c":
case "—c":
count = BaseFunc.count_charsNum(readPath);
str = readPath.split("/")[ (readPath.split("/").length-1) ];
str += ", 字符數:";
str += count;
WriteCount.writeCount(str, writePath);
break;
case "-w":
case "—w":
count = BaseFunc.count_wordsNum(readPath);
str = readPath.split("/")[ (readPath.split("/").length-1) ];
str += ", 單詞數:";
str += count;
WriteCount.writeCount(str, writePath);
break;
case "-l":
case "—l":
count = BaseFunc.count_linesNum(readPath);
str = readPath.split("/")[ (readPath.split("/").length-1) ];
str += ", 行數:";
str += count;
WriteCount.writeCount(str, writePath);
break;
}
}
}
WC項目反思與總結