WC individual events (jJAVA achieve)
A, Github Address: https://github.com/GordonKowk/WC_Item
Two, PSP form
PSP2.1 | Personal Software Process Stages | Estimated time consuming (minutes) | The actual time-consuming (minutes) |
---|---|---|---|
Planning | plan | 30 | 36 |
· Estimate | • Estimate how much time this task requires | 30 | 30 |
Development | Develop | 960 | 784 |
· Analysis | · demand analysis | 50 | 50 |
· Design Spec | Generate design documents | 30 | 43 |
· Design Review | · Design Review | 20 | 20 |
· Coding Standard | · Code Specification | 20 | 20 |
· Design | · Specific design | 80 | 60 |
· Coding | · Specific coding | 750 | 681 |
· Code Review | · Code Review | 30 | 30 |
· Test | · Test (self-test, modify the code, submit modifications) | 180 | 180 |
Reporting | report | 60 | 85 |
· Test Report | · testing report | 60 | 60 |
· Size Measurement | · Computing workload | 20 | 20 |
· Postmortem & Process Improvement Plan | · Hindsight, and propose process improvement plan | 40 | 40 |
total | 2360 | 2159 |
Third, the problems encountered & problem-solving ideas:
1) started a project when listening distressed, because the first time I went to run a java file (OMG, I found that the regulation is to Taiyuan, the command line) with cmd, but after learning is also relatively simple. Project made a number of java files on the command line to compile more, and finally selected the main class to run. Because I use MyEclipse, write java comes with the package, the package must be removed after not being given cmd enable runtime.
2) Whatever the function, to write a switch to judge each Processro, starting from simple, basic functions -c, -w, -l, -a function are our classroom contact, and how the contents of the file into the buffer is learned. You can say different, there is -a statistical judgment on the comment line, "\\" if there is one line of text can be learned by judgment, "/ * ...... * /" you can first determine the header comments to make the judgment in Notes status, go looking for the end. Function determination code is determined as a single element (the first element arr [0] is usually "-c" "-, this is not a path string w" and the like can not provide file) being given, I the "-x" graphical interface and "exit" two judgments release switch.
3) recursive call. Statistics in line with the current folder under the required documents, including subfolders. For the current directory, as arr [length-1] is the last element, that is, you would have wanted the file path statistics. Separated by the String class substring (), LastIndexOf () method of the parent folder name and file extension, with file.isFile () and file.isDirectory () and other statistical methods to judge the current file directory folder number and name, file number and extension of the same name, these data are placed in different array of strings inside. For a child file, I create a recursive method sonProcessor (), good statistics and statistical file folder name suffix before accepting data. The same recursive method for an array of folders where each folder Road King once again statistics, if there is, continue to call their own (doing so will make the output statistics from the beginning of the innermost folder), until there is no file. Finally, the output data of the problem, as I just wrote a text input stream, gave way to four function calls, resulting in the statistical data would have been out of a total of a 3552 word document, reached in the second statistics over 8000, and finally I separated four different text transport stream only solve the problem (I do not know if there is a better way, because so much of the text delivery is certainly unrealistic).
4) wildcard problem. I started writing would be more to consider whether to go after the "regular expression" (actually a regular expression is more judgmental than the switch), but I do recursive function can be found substring String class (), LastIndexOf () method for wildcards "*", the file path to intercept the last occurrence of "\" and. "" middle of nowhere, is the "*" wildcards, so before you can add a switch to determine if it is "*" appeared, direct call recursion.
5) Finally, a graphical interface, personal feeling is relatively simple, and I designed the interface with six buttons and comes with a text field, respectively -c, -w, -l, -a, comprehensive and exit functions I define an integer Type, function buttons have given listeners can call FileChooser, and each button will change the value of output corresponding statistics Type of content.
Fourth, Design and Implementation
Only three major categories, the main class Wc, function and interface class Function_Directory class GUI_Frame.
The main call flow:
Fifth, test run
Test files include: three java files, a txt file, two unrelated folders nested directories (three java files, one with three sub-folders and files java)
Wc.java run inside the CMD interface:
Basic functions and extensions -a:
-S recursive call with wildcards "*":
graphic interface:
Wc.java
static boolean TRUE_OR_NOT = true;
public static void main(String[] args){
System.out.println("*-------------------WC统计-------------------*");
System.out.println("基础功能说明:");
System.out.println(" 统计字符数:-c [您要查找的文件路径]");
System.out.println(" 统计词数: -w [您要查找的文件路径]");
System.out.println(" 统计行数: -l [您要查找的文件路径]");
System.out.println("");
System.out.println("拓展功能说明:");
System.out.println(" 统计空行、代码行、注释行: -a [您要查找的文件路径]");
System.out.println(" 递归处理: -s [您要查找的文件路径]");
System.out.println("");
System.out.println("高级功能说明:");
System.out.println(" 图形化界面:-x");
System.out.println("");
System.out.println("若想退出程序请输入:退出");
System.out.println("*--------------------------------------------*");
System.out.println("请输入指令:");
while(TRUE_OR_NOT){
Scanner command = new Scanner(System.in);
String[] arr = command.nextLine().split("\\s");
int len = arr.length;
Function_Directory FD = new Function_Directory();
FD.commandProcessor(arr,len,0,arr[arr.length-1]); //把数据都交给FD对象里面
}
}
GUI_Frame.java
private static final long serialVersionUID = 1L;
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension screenSize = kit.getScreenSize();
static JTextArea textArea = new JTextArea();
private JPanel chooseBar = new JPanel();
private JButton count_c = new JButton("字符数");
private JButton count_w = new JButton("词数");
private JButton count_l = new JButton("行数");
private JButton count_a = new JButton("拓展功能");
private JButton count_all = new JButton("总结");
private JButton count_close = new JButton("关闭");
private Font buttonFont = new Font("宋体",Font.BOLD,25);
int charNum = 0;
int wordNum = 0;
int lineNum = 0;
int blankLineNum = 0;
int codeLineNum = 0;
int annotationLineNum = 0;
int Type = 0;
ArrayList<Integer> resultList = null;
GUI_Frame(){
setTitle("WC统计");
setSize(2*screenSize.width/4,3*screenSize.height/4);
setLocation(2*screenSize.width/4,screenSize.height/8);
initEventListeners();
add(chooseBar,BorderLayout.NORTH);
initChooseBar();
initTextArea();
}
private void initChooseBar(){ //顶部选项栏设置
chooseBar.add(count_c);
chooseBar.add(count_w);
chooseBar.add(count_l);
chooseBar.add(count_a);
chooseBar.add(count_all);
chooseBar.add(count_close);
count_c.setFont(buttonFont);
count_w.setFont(buttonFont);
count_l.setFont(buttonFont);
count_a.setFont(buttonFont);
count_all.setFont(buttonFont);
count_close.setFont(buttonFont);
}
private void initTextArea(){
textArea.setFont(new Font("宋体", Font.PLAIN, 30));
textArea.setMargin(new Insets(3,10,3,10));
textArea.setLineWrap(true);
textArea.setDragEnabled(true);
JScrollPane panel = new JScrollPane(textArea,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
getContentPane().add(panel, BorderLayout.CENTER);
}
private void initEventListeners(){
count_c.addActionListener( this::countC );
count_w.addActionListener( this::countW );
count_l.addActionListener( this::countL );
count_a.addActionListener( this::countA );
count_all.addActionListener( this::countAll );
count_close.addActionListener( this::countClose);
}
private void countC(ActionEvent event){
Type = 1;
CountStart();
}
private void countW(ActionEvent event){
Type = 2;
CountStart();
}
private void countL(ActionEvent event){
Type = 3;
CountStart();
}
private void countA(ActionEvent event){
Type = 4;
CountStart();
}
private void countAll(ActionEvent event){
Type = 5;
CountStart();
}
private void countClose(ActionEvent event){
Type = 0;
System.exit(0);
}
public void CountStart(){
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
chooser.showDialog(new JLabel(), "选择要统计的文件");
File file = chooser.getSelectedFile();
try{
String encoding = "GBK";
InputStreamReader readFile = new InputStreamReader(new FileInputStream(file),encoding);
BufferedReader fileContent = new BufferedReader(readFile);
switch(Type){
case 1:
charNum = Function_Directory.charsCounter(fileContent);
textArea.append(file+":\n"+"字符数:" + charNum + "\n\n");
break;
case 2:
wordNum = Function_Directory.wordsCounter(fileContent);
textArea.append(file+":\n词数:" + wordNum+"\n\n");
break;
case 3:
lineNum = Function_Directory.linesCounter(fileContent);
textArea.append(file+":\n行数:" + lineNum+"\n\n");
break;
case 4:
resultList = Function_Directory.Expand_Count(fileContent);
blankLineNum = resultList.get(0);
codeLineNum = resultList.get(1);
annotationLineNum = resultList.get(2);
textArea.append(file+":\n空行数:" + blankLineNum + "\n代码行数:"
+ codeLineNum + "\n注释行数" + annotationLineNum+"\n\n");
break;
case 5:
charNum = Function_Directory.charsCounter(fileContent);
wordNum = Function_Directory.wordsCounter(fileContent);
lineNum = Function_Directory.linesCounter(fileContent);
resultList = Function_Directory.Expand_Count(fileContent);
blankLineNum = resultList.get(0);
codeLineNum = resultList.get(1);
annotationLineNum = resultList.get(2);
textArea.append(file+":\n"+"字符数:" + charNum + "\n词数:"
+ wordNum + "\n行数:" + lineNum + "\n空行数:" + blankLineNum + "\n代码行数:"
+ codeLineNum + "\n注释行数" + annotationLineNum+"\n");
}
}catch(IOException e){
System.out.println("文件路径错误或者文件不支持喔~");
e.printStackTrace();
}
}
public static void main(String[] args) {
GUI_Frame GF = new GUI_Frame();
GF.setVisible(true);
}
Function_Directory.java
public void commandProcessor(String[] arr,int len,int start,String fileName){
if(arr[0].equals("-x")){ //由于只输入一个元素会报错,“-x”和“退出”先提前判断
GUI_Frame GF = new GUI_Frame(); //一个图形化界面
GF.setVisible(true);
} else if(arr[0].equals("退出")) { Wc.TRUE_OR_NOT = false;
} else{
try{
for(int i = start;i < len-1||i == 0;i++){
String fileUrl = arr[arr.length-1].substring(arr[arr.length-1].lastIndexOf("\\")+1,arr[arr.length-1].lastIndexOf("."));
System.out.println(fileUrl);
if(fileUrl.equals("*")) recursiveProcessor(arr); //判断通用符号“*”
else{
String encoding = "GBK";
File file = new File(fileName);
InputStreamReader readFile = new InputStreamReader(new FileInputStream(file),encoding);
BufferedReader fileContent = new BufferedReader(readFile);
switch(arr[i]){
case "-c":
charsCounter(fileContent);
break;
case "-w":
wordsCounter(fileContent);
break;
case "-l":
linesCounter(fileContent);
break;
case "-a":
Expand_Count(fileContent);
break;
case "-s":
recursiveProcessor(arr);
break;
default:break;
}
}}
}catch(Exception e){
System.out.println(arr[0]+"不是功能指令喔~,看看是不是哪里输入错误了。");
e.printStackTrace();
}
}
}
static int charsCounter(BufferedReader fileContent) throws IOException{
String lineCount = null;
int charNum = 0;
while((lineCount = fileContent.readLine()) != null){
lineCount = lineCount.trim();
for(int i = 0;i < lineCount.length();i++){
char ch = lineCount.charAt(i);
if(ch != '\n' && ch != '\t' && ch != ' ')
charNum++;
}
}
System.out.println("字符数:" + charNum);
return charNum;
}
static int wordsCounter(BufferedReader fileContent) throws IOException{
String REGEX = "[a-zA-Z]+\\b"; //判断词的正则表达式
String lineCount = null;
int wordNum = 0;
Pattern pattern = Pattern.compile(REGEX);
while((lineCount = fileContent.readLine()) != null){
lineCount = lineCount.trim();
Matcher matcher = pattern.matcher(lineCount);
while(matcher.find()){
wordNum++;
}
}
System.out.println("词数:" + wordNum);
return wordNum;
}
static int linesCounter(BufferedReader fileContent) throws IOException{
int lineNum = 0;
String lineCount = null;
while((lineCount = fileContent.readLine()) != null){ lineNum++; }
System.out.println("行数:" + lineNum);
return lineNum;
}
static ArrayList<Integer> Expand_Count(BufferedReader fileContent)throws IOException{
String lineCount = null;
ArrayList<Integer> resultList = new ArrayList<Integer>();
boolean isComment = false;
int codeLineNum = 0;
int blankLineNum = 0;
int annotationLineNum = 0;
while((lineCount = fileContent.readLine()) != null){ //对注释行的判断
if(lineCount.contains("/*")){
annotationLineNum++;
isComment = true;
} else if(isComment){
annotationLineNum++;
if(lineCount.contains("*/")){ isComment = false; }
} else if(lineCount.contains("//")){
annotationLineNum++;
} else if(lineCount.trim().length() > 1){
codeLineNum++;
} else{
blankLineNum++;
}
}
System.out.println("空行数:" + blankLineNum);
System.out.println("代码行数:" + codeLineNum);
System.out.println("注释行数:" + annotationLineNum);
resultList.add(blankLineNum);
resultList.add(codeLineNum);
resultList.add(annotationLineNum);
return resultList;
}
public void recursiveProcessor(String[] arr) throws IOException{
int LA = arr.length;
int n = 0;
String fileUrl = arr[LA-1].substring(0,arr[LA-1].lastIndexOf("\\")); //找到文件路径最先出现“\”的位置
String fileEnd = arr[LA-1].substring(arr[LA-1].lastIndexOf(".")); //找到文件路径最先出现“.”的位置
List<File> fileList = new ArrayList<File>();
File file = new File(fileUrl);
File[] files = file.listFiles();
String[] names = file.list();
String[] CompletNames = null;
for (File f : files) {
if (f.isDirectory()){ n++; }
}
CompletNames = new String[n];
n = 0;
if (files == null) {}
for (File f : files) {
if (f.isFile()&&f.getName().endsWith(fileEnd)) { fileList.add(f); }
if (f.isDirectory()){
CompletNames[n] = arr[LA-1].substring(0,arr[LA-1].lastIndexOf("\\"))+"\\"+f.getName();
System.out.println(CompletNames[n]);
n++;
}
}
for (File f1 : fileList) {
System.out.println(fileUrl+"\\"+f1.getName());
String encoding = "GBK";
InputStreamReader rC = new InputStreamReader(new FileInputStream(f1),encoding);
InputStreamReader rW = new InputStreamReader(new FileInputStream(f1),encoding);
InputStreamReader rL = new InputStreamReader(new FileInputStream(f1),encoding);
InputStreamReader rA = new InputStreamReader(new FileInputStream(f1),encoding);
BufferedReader C = new BufferedReader(rC);
BufferedReader W = new BufferedReader(rW);
BufferedReader L = new BufferedReader(rL);
BufferedReader A = new BufferedReader(rA);
charsCounter(C);
wordsCounter(W);
linesCounter(L);
Expand_Count(A);
C.close(); //我试过只写一个文本输入流,统计结果会累积,数据错误
W.close(); //由于写入太多输入流,希望想找到更好的办法
L.close();
A.close();
}
System.out.println("*-----------------------------*");
if (CompletNames!=null) sonProcessor(CompletNames,fileEnd);
}
String[] N = Names; //寻找子文件,并把子文件里面符合要求的文件统计出来
int LengthA = N.length; //这里我运用了递归,但是发现是先递归到最里层才开始统计
for(int i=0;i<Names.length;i++){
int n = 0;
String fileUrl = N[i];
String fileEnd = End;
List<File> fileList = new ArrayList<File>();
File file = new File(fileUrl);
File[] files = file.listFiles();
String[] names = file.list();
String[] CompletNames = null;
for (File f : files) {
if (f.isDirectory()){ n++; }
}
CompletNames = new String[n];
n =0;
if (files == null) {}
for (File f : files) {
if (f.isFile()&&f.getName().endsWith(fileEnd)) { fileList.add(f); }
if (f.isDirectory()){
CompletNames[n] = N[i]+"\\"+f.getName();
System.out.println(CompletNames[n]);
n++;
}
}
if (CompletNames!=null) sonProcessor(CompletNames,fileEnd);
for (File f1 : fileList) {
System.out.println(N[i]+"\\"+f1.getName());
String encoding = "GBK";
InputStreamReader rC = new InputStreamReader(new FileInputStream(f1),encoding);
InputStreamReader rW = new InputStreamReader(new FileInputStream(f1),encoding);
InputStreamReader rL = new InputStreamReader(new FileInputStream(f1),encoding);
InputStreamReader rA = new InputStreamReader(new FileInputStream(f1),encoding);
BufferedReader C = new BufferedReader(rC);
BufferedReader W = new BufferedReader(rW);
BufferedReader L = new BufferedReader(rL);
BufferedReader A = new BufferedReader(rA);
charsCounter(C);
wordsCounter(W);
linesCounter(L);
Expand_Count(A);
C.close();
W.close();
L.close();
A.close();
System.out.println("*-----------------------------*");
}
}
}
六、项目总结:
这次项目让我感受最深的是做这个项目的计划,先给自己一个规划,做出要想做的框架流程,想好自己应该干嘛,用多少时间,应该怎么去测试,以前的课设我是没有注意到这些的,这也让我看到做一个项目的严谨性。之前的java程序我都是通过设计图形化界面去运行的,没有像这次在命令行里面运行,学会了如何在命令行编译与运行java文件。递归调用的实现也是我印象最深刻的,文件夹和文件的路径由于循环让我自己都搞晕了,不断调试,不断找准切分位置,不断有报错,文件夹数组长度不能过长,路径不能错误,有时数据会卡住循环进行。递归的实现是我用时最多的部分。但是因为想去搞懂,从网上找资料,询问同学,学到不少,也能想出适合自己的方法。现在是个人项目,我期待在后面的项目能收获更多。