Java课程的综合实验…大三的时候写过的,不过现在回头看,发现写得真烂,所以在学习Java过程中重构了代码.
基本不算重构而是重写…改的时候差点看不懂自己写过什么…好了言归正传:
实验的要求如下:
一、题目:综合性实验 Java源代码分析程序
二、类型:综合型、探索型
三、目的:初步掌握运用面向对象方法编写应用程序,掌握类、对象、封装等;了解并应用Java语言的字符串处理、文本文件的读写
四、内容:
1.背景描述:
(1)Java语言共有50个关键字。
(2)Java源程序是以“.java”为扩展名的文本文件。
(3)可以考虑在Java源程序中的行共有3种:
代码行,可运行的Java源代码。例如:
int n = 10;
注释行,3种注释均可。例如:
/**
文档注释
*/
/*
多行注释
/
//单行注释
空行,既无代码,也无注释;
(4)特殊行的处理方法
如果有以下行尾单行注释的情况,将该行判定为代码行。
int number; //number表示人数
int n; /n表示数量/
如果有以下行尾多行注释的情况,第1行判定为代码行,第二行判定为注释行。
int number; / number为整型
表示人数 */
假设被分析程序源码无其他特殊情况,如:
int /人数/ number;
2. 项目名和类名为JavaCodeAnalyzer,主类名等其他类名自行定义。
实现功能:
(1) 程序运行时要求输入一个目录的名称。目录不存在或不是目录要提示错误并重新输入。
(2) 找出输入目录中所有的Java源程序文件(文件扩展名为“.java”), 并进行源程序文件进行分析。
需要分析的结果有:
目录中源程序文件个数
所有源程序文件总的字节数
所有源程序文件中代码行数、注释行数、空行数及总行数。说明:行以回车结束。
(3) 统计并按从多到少输出所有源程序文件中使用的Java关键字及其出现次数。
(4) 统计分析的结果除在屏幕显示外,还需要存储到一个文本文件中,文件内容应该如下:
目录名称:XXXXX(绝对路径方式)
共有源程序文件XX个,总的大小为:XXXXXX 字节
源程序文件总行数:xxxx,其中:
代码行数:xxx,占xx.xx%
注释行数:xxx,占xx.xx%
空白行数:xxx,占xx.xx%
源程序文件中使用过的关键字有(按使用次数降序排列):
关键字1:xx次
关键字2:xx次
关键字3:xx次
关键字4:xx次
关键字5:xx次
本次分析时间:年-月-日,时-分-秒
注意:统计关键字使用次数时,要排除注释中出现的关键字和字符串直接量中出现的关键字。
好了,总的来说可以分成以下几个模块:
1.判断输入目录是否正确
2.搜索Java文件并保存到ArrayList
3.计算Java文件个数和总大小
4.统计源文件的代码行数,注释行数等
5.统计源文件的关键字出现次数
6.将输出结果保存到文件
7.输出计算用时
其中
2,3可以参考我的文章 [Java]统计指定目录中文件的个数和总的大小
4可以参考[Java]统计Java源文件代码行数,注释行数,空白行数
5可以参考 [Java]统计目录下Java源文件的关键字出现次数
※重构代码中对6,7不做实现
public static String getPathName() {
System.out.println("输入目录路径:");
Scanner keyboardInput = new Scanner(System.in);
String pathName = null;
File root = null;
while (true) {
pathName = keyboardInput.nextLine();
root = new File(pathName);
if (root.isFile()) {
System.out.println("输入不是目录,请重新输入");
} else if (!root.exists()) {
System.out.println("目录不存在,请重新输入");
} else {
break;
}
}
return pathName;
}
public void searchFiles() {
File[] files = root.listFiles();
int length = files.length;
for (int i = 0; i < length; i++) {
if (files[i].isDirectory()) {
root = files[i];
searchFiles();
} else {
if (files[i].getName().endsWith(".java"))
fileList.add(files[i]);
}
}
}
public void countFiles() {
long totalSize = 0;
System.out.println("目录名称:" + fileList.get(0).getParent());
System.out.println("文件数:" + fileList.size());
for (int i = 0; i < fileList.size(); i++) {
totalSize += fileList.get(i).length();
}
System.out.println("文件总大小(bytes):" + totalSize);
}
代码与我的文章[Java]统计Java源文件代码行数,注释行数,空白行数一致.这里仅贴代码,详细解析请参考文章
import java.io.*;
import java.util.ArrayList;
import java.text.DecimalFormat;
public class CodeAnalyzer {
public void codeAnalyze(ArrayList<File> fileList) {
double rowsCount = 0;
double commentsCount = 0;
double blanksCount = 0;
double codesCount = 0;
DecimalFormat df = new DecimalFormat("#.##");
for (File file : fileList) {
try {
rowsCount += countRows(file);
blanksCount += countBlanks(file);
commentsCount += countComments(file);
codesCount = rowsCount - blanksCount - commentsCount;
} catch (IOException e) {
e.printStackTrace();
}
}
//输出结果
System.out.println("源程序文件总行数:" + (int) rowsCount);
System.out.println("代码行数:" + (int) codesCount + ",占" + df.format(codesCount / rowsCount * 100) + "%");
System.out.println("注释行数:" + (int) commentsCount + ",占" + df.format(commentsCount / rowsCount * 100) + "%");
System.out.println("空白行数:" + (int) blanksCount + ",占" + df.format(blanksCount / rowsCount * 100) + "%");
}
public int countRows(File file) throws IOException {
BufferedReader input = new BufferedReader(new FileReader(file));
int rows = 0;
while (input.readLine() != null) {
rows++;
}
return rows;
}
public int countBlanks(File file) throws IOException {
BufferedReader input = new BufferedReader(new FileReader(file));
int blanks = 0;
String line = null;
while ((line = input.readLine()) != null) {
if (line.trim().equals("")) blanks++;
}
return blanks;
}
public int countComments(File file) throws IOException {
BufferedReader input = new BufferedReader(new FileReader(file));
int comments = 0;
String line = null;
while ((line = input.readLine()) != null) {
line = line.trim();
if (line.startsWith("//")) {
//单行注释
comments++;
} else if (line.startsWith("/*")) {
//多行及文档注释
comments++;
while (!line.endsWith("*/")) {
line = input.readLine().trim();
comments++;
}
} else if (line.contains("/*")) {
//下行尾多行注释
line = input.readLine().trim();
if (line.endsWith("*/")) comments++;
}
}
return comments;
}
}
与4一样,这里仅贴代码,详情解析到-> [Java]统计目录下Java源文件的关键字出现次数
import java.io.*;
import java.util.*;
public class KeywordsAnalyzer {
Map keywords;
final String[] KEYWORDS = {
//50个关键字
"abstract", "assert", "boolean", "break", "byte",
"case", "catch", "char", "class", "const",
"continue", "default", "do", "double", "else",
"enum", "extends", "final", "finally", "float",
"for", "goto", "if", "implements", "import",
"instanceof", "int", "interface", "long", "native",
"new", "package", "private", "protected", "public",
"return", "strictfp", "short", "static", "super",
"switch", "synchronized", "this", "throw", "throws",
"transient", "try", "void", "volatile", "while"
};
public KeywordsAnalyzer() {
keywords = new HashMap();
for (String word : KEYWORDS) {
keywords.put(word, 0);
}
}
public void keywordsAnalyze(ArrayList<File> fileList) {
for (File file : fileList) {
try {
countKeyWords(file);
} catch (IOException e) {
e.printStackTrace();
}
}
//排序并输出结果
List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(keywords.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
int count = 0;
System.out.println("\n源程序文件中使用过的关键字有(按使用次数降序排列):");
for(int i=0;i<5;i++){
System.out.println("关键字 "+list.get(i).getKey()+": "+list.get(i).getValue()+"次");
}
}
public void countKeyWords(File file) throws IOException {
BufferedReader input = new BufferedReader(new FileReader(file));
String line = null;
while ((line = input.readLine()) != null) {
line = line.trim();
if (line.startsWith("//")) continue; //不处理单行注释
else if (line.contains("/*")) {
//多行,文档与尾行注释
if (!line.startsWith("/*")) matchKeywords(line);//第一行算代码,其余算注释
while (!line.endsWith("*/")) {
line = input.readLine().trim();
}
}
matchKeywords(line); //对代码行进行统计
}
}
public void matchKeywords(String line) {
String[] wordList = line.replaceAll("\\W", " ").split(" ");
for (int i = 0; i < wordList.length; i++) {
for (int j = 0; j < 50; j++) {
if (wordList[i].equals(KEYWORDS[j])) {
int count = (int) keywords.get(KEYWORDS[j]);
keywords.put(KEYWORDS[j], count + 1);
}
}
}
}
}
测试Timer.java,得到结果:
包含源代码,可执行的jar以及测试用例.