一、题目介绍与分析
编写一个Java应用程序,对单个Java源程序文件及某个目录中的所有Java源程序文件(包括子目录)进行分析,分析内容包括:
1)Java源程序文件个数,对目录分析进行分析时需要。
2)Java源程序中的字符个数,对目录分析时是其中所有源程序文件的字符个数总和。
3)Java源程序文件中的注释的个数,即源程序文件中共有多少个注释,包括:单行注释和多行注释。对目录分析时是其中所有源程序文件的总和。
4)Java源程序文件中的注释的字符个数,即源程序文件中所有注释的字符数之和。对目录分析时是其中所有源程序文件的总和。
5)Java源程序文件中关键字使用情况,即源程序文件各个关键字使用了多少次。对目录分析时是其中所有源程序文件的总和。
具体要求如下:
- 程序运行首先显示所示的菜单:
---------------- MENU ------------- 1.分析目录或者源程序文件 2.查看已有的分析结果 0.退出 ---------------------------------------- 请选择:
-
选择菜单项目1时,首先要求输入要分析的目录名或Java源程序文件名。 1)如果输入的目录或文件名不存在,提示不存在;输入的文件名的扩展名不是“.java”时提示不是Java源程序文件。 2)如果输入的是一个Java源程序文件名,对该源程序文件进行分析。 3)如果输入的是一个目录名,对该目录中所有的源程序文件进行分析。 4)分析的结果存储到一个文本文件中,在当前目录中建立一个data目录,结果文件放在data目录中。 分析目录时结果文件名:D_目录名_Result.txt,例如:D_lang_Result.txt 分析源程序文件时结果文件名:F_源程序文件名_Result.txt,例如:F_String.java_Result.txt 5)结果文件中内容的格式: 第1行:分析目录 : C:Program\Files\Java\jdk1.8.0_31\src\java 第2行:空行 第3行:Java源程序文件个数: 1866 (分析文件时无此行) 第4行:源程序中字符总个数 : 29022541 第5行:注释总个数 : 57349 第6行:注释总的字符数 : 17559371 第7行:空行 第8行:关键字使用情况如下: 第9行:[int = 27705] (从第9行开始输出各个关键字及其使用的次数,每行一个) 说明: 分析结束时,不显示分析结果,结果存储到文本文件,显示如下提示: 目录分析结束, 分析结果存放在文件[data/D_util_Result.txt]! 或者: 文件分析结束, 分析结果存放在文件[data/F_String.java_Result.txt]! 关键字输出时,按使用次数从大到小排序,次数相同时,按字母顺序排序。 Java语言的所有关键字
public static final String[] KEYWORDS = { "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", "short", "static",
"strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void",
"volatile", "while" };
-
查看已有的分析结果要求 选择菜单项目2时,首先列出已经分析并存储的结果,如下: ----------------------------------- 1–D_test.java_Result.txt 2–D_test2.java_Result.txt ------------------------------------ 输入要查看的文件编号: 即列出data目录中存储的所有分析结果文件,并给出一个序号。 输入要查看的文件序号后,显示该文件中的内容。例如下: ------------------------------------------------------------------------------------------------------ 分析目录: D:\Java\Java实验题\Comprehensive\test.java Java源程序文件个数 :5 源程序中字符总个数 :9432 注释总个数 :59 注释总的字符数 :2361 关键字的使用情况如下: [public = 32] [return = 14] [static = 14] [double = 12] [if = 10] [private = 10] [this = 10] [void = 10] [int = 8] [new = 8] [char = 5] [class = 5] [for = 5] [package = 5] [boolean = 4] [final = 4] [import = 4] [while = 2] [break = 1] [else = 1] ----------------------------------------------------------------------------------------------
二、相关提示
-
分析注释个数和注释的字符数时,假设没有注释嵌套的问题。即测试用的文件和目录中没有如下情况: /** //注释1 */ // 注释2 /* */ -
分析注释个数和注释的字符数时,假设字符串直接量中没有注释形式,即没有下面的情况: String s = “/abcd/”; -
分析关键字使用次数时,注意以下几种情况不能计算关键字个数: (1) 注释中出现的关键字,例如下面的int不能计数 /** * int k=0; */ (2) 字符串直接量中的关键字,例如下面的int不能计数 System.out.println(“input a int: ”);
(3) 注意整字识别,例如 println 中的int不是关键字,不能计数。 -
如果使用正则表达式进行编程,除基本的正则表达式使用外,可以参考Java的如下两个类: java.util.regex.Pattern java.util.regex.Matcher
三、源码
- 目录结构
- 各个类的介绍
- 运行结果
- 代码
Functions类
package cn.zg.frame;
import cn.zg.module.Comment;
import cn.zg.module.Keyword;
import cn.zg.module.LookUpFile;
import cn.zg.module.SaveFile;
import cn.zg.utils.*;
import java.io.File;
import java.util.Objects;
import java.util.Scanner;
public class Functions {
public static final String JAVA_SUFFIX=".java";
public static void evaluate() {
String input=new Scanner(System.in).next();
System.out.println();
File file = new File(input);
if(!file.exists()){
System.out.print("输入的目录或文件名不存在,请重新选择:");
evaluate();
}else if(!input.toLowerCase().endsWith(JAVA_SUFFIX)){
System.out.print("您输入的不是Java源程序文件,请重新输入:");
evaluate();
}else if(file.isDirectory()){
dirEvaluate(input);
}else{
fileEvaluate(input);
}
}
public static void dirEvaluate(String dir) {
System.out.println("分析目录 :"+dir);
System.out.println();
System.out.println("Java源程序文件个数 :"+dir);
System.out.println("源程序中字符总个数 :"+String.format("%10d",InTotalCharsUtil.dirCharsCount(dir)) );
System.out.println("注释总个数 :"+String.format("%10d",Comment.dirCommentCounts(dir)));
System.out.println("注释总的字符数 :"+String.format("%10d",Comment.dirCommentChars(dir)));
System.out.println();
System.out.println("关键字的使用情况如下:");
Keyword.print(dir);
SaveFile.saveDir(dir);
}
public static void fileEvaluate(String file) {
System.out.println("分析文件 :"+file);
System.out.println();
System.out.println("源程序中字符总个数 :"+String.format("%10d",InTotalCharsUtil.javaCharsCount(file)) );
System.out.println("注释总个数 :"+String.format("%10d",Comment.fileCommentCounts(file)));
System.out.println("注释总的字符数 :"+String.format("%10d",Comment.fileCommentChars(file)));
System.out.println();
System.out.println("关键字的使用情况如下:");
Keyword.print(file);
SaveFile.saveFile(file);
}
public static void lookUp() {
File file = new File("src\\data");
if(file.isDirectory()){
File[] files = file.listFiles();
if (files != null&&files.length>0) {
System.out.println("-----------------------------------");
for (File f : files) {
System.out.println(f.getName());
}
System.out.println("------------------------------------");
}else{
System.out.print("目前还未进行文件或者目录的分析,请选择其他功能:");
Start.function();
}
System.out.print("输入要查看的文件编号:");
int input=new Scanner(System.in).nextInt();
if(input<1||input> Objects.requireNonNull(files).length){
System.out.print("输入的文件编号有误,请重新输入文件编号:");
input=new Scanner(System.in).nextInt();
System.out.println();
System.out.println();
System.out.println();
}
System.out.println();
System.out.println();
if (files != null) {
LookUpFile.lookUp(files[input-1].getAbsolutePath());
}
}
}
}
初始界面Start类
package cn.zg.frame;
import java.util.Scanner;
import static cn.zg.frame.Functions.evaluate;
import static cn.zg.frame.Functions.lookUp;
public class Start {
public static final int EVALUATE_DIR_OR_FILE=1;
public static final int LOOK_UP_RESULT=2;
public static final int EXIT=0;
public static void mainFrame(){
System.out.println("-----------MENU-----------");
System.out.println(" 1.分析目录或者源程序文件 ");
System.out.println(" 2.查看已有的分析结果 ");
System.out.println(" 0.退出 ");
System.out.println("--------------------------");
System.out.print(" 请选择:");
function();
}
public static void function() {
int input=new Scanner(System.in).nextInt();
if(input==EVALUATE_DIR_OR_FILE){
System.out.print("请输入要分析的目录名或Java源程序文件名:");
evaluate();
}else if(input==LOOK_UP_RESULT){
System.out.println();
System.out.println();
lookUp();
System.out.println();
System.out.println();
}else if(input==EXIT){
System.exit(0);
}else{
mainFrame();
}
}
}
启动类Main
package cn.zg.main;
import cn.zg.frame.Start;
public class Main {
public static void main(String[] args) {
Start.mainFrame();
}
}
Comment类:
package cn.zg.module;
import cn.zg.utils.CommentCountsAndCharsUtil;
import cn.zg.utils.TextIntoListUtil;
import java.io.File;
import java.util.ArrayList;
public class Comment {
public static long fileCommentCounts(String filePath){
ArrayList<String> list = TextIntoListUtil.fileList(filePath);
long[] countsAndChars = CommentCountsAndCharsUtil.operateNote(list);
return countsAndChars[0];
}
public static long fileCommentChars(String filePath){
ArrayList<String> list = TextIntoListUtil.fileList(filePath);
long[] countsAndChars = CommentCountsAndCharsUtil.operateNote(list);
return countsAndChars[1];
}
public static long dirCommentCounts(String dirPath){
long count=0;
File dir = new File(dirPath);
File[] files = dir.listFiles();
if(files==null){
return 0;
}
for (File f : files) {
if(f.isFile()){
count+=fileCommentCounts(f.getAbsolutePath());
}else{
count+=dirCommentCounts(f.getAbsolutePath());
}
}
return count;
}
public static long dirCommentChars(String dirPath){
long count=0;
File dir = new File(dirPath);
File[] files = dir.listFiles();
if(files==null){
return 0;
}
for (File f : files) {
if(f.isFile()){
count+=fileCommentChars(f.getAbsolutePath());
}else{
count+=dirCommentChars(f.getAbsolutePath());
}
}
return count;
}
}
FileID类
package cn.zg.module;
import java.io.Serializable;
public class FileID implements Serializable {
private static final long serialVersionUID=1L;
private int id;
public FileID() {
}
public FileID(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Keyword类
package cn.zg.module;
import cn.zg.utils.KeySelectUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Keyword {
public static ArrayList<String> writeIntoFile(String fileName){
File file = new File(fileName);
ArrayList<String> returnList = new ArrayList<>();
Map<String, Integer> map;
if(file.isFile()){
map = KeySelectUtil.fileCountKeyWords(fileName);
}else{
map = KeySelectUtil.dirCountKeyWords(fileName);
}
List<Map.Entry<String, Integer>> list = null;
if (map != null) {
list = KeySelectUtil.mapIntoListAndSort(map);
}
if (list != null) {
for (Map.Entry<String, Integer> stringIntegerEntry : list) {
if(stringIntegerEntry.getValue()>0){
returnList.add("["+String.format("%-15s",stringIntegerEntry.getKey())+
"="+String.format("%5d",stringIntegerEntry.getValue())+"]");
}
}
}
return returnList;
}
public static void print(String fileName){
File file = new File(fileName);
Map<String, Integer> map;
if(file.isFile()){
map = KeySelectUtil.fileCountKeyWords(fileName);
}else{
map = KeySelectUtil.dirCountKeyWords(fileName);
}
List<Map.Entry<String, Integer>> list = null;
if (map != null) {
list = KeySelectUtil.mapIntoListAndSort(map);
}
if (list != null) {
for (Map.Entry<String, Integer> stringIntegerEntry : list) {
if(stringIntegerEntry.getValue()>0){
System.out.println("["+String.format("%-15s",stringIntegerEntry.getKey())+
"="+String.format("%5d",stringIntegerEntry.getValue())+"]");
}
}
}
}
}
LookUpFile类
package cn.zg.module;
import cn.zg.frame.Functions;
import cn.zg.frame.Start;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class LookUpFile {
public static void lookUp(String absolutePath) {
try(BufferedReader bufferedReader = new BufferedReader(new FileReader(absolutePath))){
String str;
while((str=bufferedReader.readLine())!=null){
System.out.println(str);
}
}catch (IOException e){
e.printStackTrace();
}
System.out.println();
System.out.println();
System.out.print("返回主菜单请输入1,返回上一层请输入2,退出请输入0:");
boolean loop=true;
while(loop){
int input=new Scanner(System.in).nextInt();
if(input==1){
System.out.println();
System.out.println();
Start.mainFrame();
loop=false;
}else if(input==0){
loop=false;
System.exit(0);
}else if(input==2){
System.out.println();
System.out.println();
Functions.lookUp();
}else{
System.out.print("输入有误!请重新输入!返回主菜单请输入1,返回上一层请输入2,退出请输入0:");
}
}
}
}
SaveFile类
package cn.zg.module;
import cn.zg.utils.InTotalCharsUtil;
import cn.zg.utils.JavaFileCountUtil;
import cn.zg.utils.OtherUtils;
import java.io.*;
import java.util.ArrayList;
public class SaveFile {
public static int getId(){
int id = 0;
try(ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("src\\id\\id.txt"))){
FileID obj = (FileID)objectInputStream.readObject();
id= obj.getId();
}catch (IOException | ClassNotFoundException e){
e.printStackTrace();
}
return id;
}
public static void setId(int id){
try(ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("src\\id\\id.txt"))){
objectOutputStream.writeObject(new FileID(id));
}catch (IOException e){
e.printStackTrace();
}
}
public static void saveDir(String dirPath){
int id=getId();
id++;
setId(id);
File file = new File(dirPath);
String path=""+id+"--D_"+file.getName()+"_Result.txt";
try(final BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("src\\data\\"+path))){
String[] strings={
"------------------------------------------------",
"分析目录 :"+dirPath,
"Java源程序文件个数 :"+ JavaFileCountUtil.javaFileCount(dirPath),
"源程序中字符总个数 :"+ InTotalCharsUtil.dirCharsCount(dirPath),
"注释总个数 :"+Comment.dirCommentCounts(dirPath),
"注释总的字符数 :"+ Comment.dirCommentChars(dirPath),
"关键字的使用情况如下:"
};
for(int i=0;i<strings.length;i++){
bufferedWriter.write(strings[i]);
bufferedWriter.newLine();
if(i==1||i==5){
bufferedWriter.newLine();
}
}
ArrayList<String> list = Keyword.writeIntoFile(dirPath);
for (String s : list) {
bufferedWriter.write(s);
bufferedWriter.newLine();
}
bufferedWriter.write("------------------------------------------------");
}catch (IOException e){
e.printStackTrace();
}
OtherUtils.returnOrNotFile(path);
}
public static void saveFile(String filePath){
int id=getId();
id++;
setId(id);
File file = new File(filePath);
String path=""+id+"--F_"+file.getName()+"_Result.txt";
try(final BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("src\\data\\"+path))){
String[] strings={
"------------------------------------------------",
"分析文件 :"+filePath,
"源程序中字符总个数 :"+ InTotalCharsUtil.javaCharsCount(filePath),
"注释总个数 :"+Comment.fileCommentCounts(filePath),
"注释总的字符数 :"+ Comment.fileCommentChars(filePath),
"关键字的使用情况如下:"
};
for(int i=0;i<strings.length;i++){
bufferedWriter.write(strings[i]);
bufferedWriter.newLine();
if(i==1||i==4){
bufferedWriter.newLine();
}
}
ArrayList<String> list = Keyword.writeIntoFile(filePath);
for (String s : list) {
bufferedWriter.write(s);
bufferedWriter.newLine();
}
bufferedWriter.write("------------------------------------------------");
}catch (IOException e){
e.printStackTrace();
}
OtherUtils.returnOrNotDir(path);
}
}
CommentCountsAndCharsUtil类
package cn.zg.utils;
import java.util.ArrayList;
public class CommentCountsAndCharsUtil {
public static final String END_OF_COMMENT="*/";
public static final String SINGLE_LINE_COMMENT="//";
public static long[] operateNote(ArrayList<String> list){
String str;
long countNote=0;
long charInNote = 0;
for(int i=0;i<list.size();i++) {
str=list.get(i);
int note1=str.indexOf("/*");
int note2=str.indexOf("//");
int note3=str.indexOf("*/");
String dm="\"(.*)\"";
if(note1!=-1&¬e3==-1) {
countNote++;
String ttt=list.get(i);
list.set(i, ttt.substring(0, note1));
charInNote+=str.substring(note1).length()+1;
str=list.get(++i);
while(!str.contains(END_OF_COMMENT)) {
if(str.contains(SINGLE_LINE_COMMENT)) {
countNote++;
}
list.set(i,"");
charInNote+=str.length()+1;
if(i<list.size()-1) {
str=list.get(++i);
}else {
break;
}
}
list.set(i,"");
charInNote+=str.length();
}else if(note2!=-1) {
countNote++;
list.set(i, str.substring(0,note2));
charInNote+=str.substring(note2).length()+1;
}else if(note1 != -1) {
countNote++;
String m1=str.substring(0, note1);
String m2=str.substring(note3+2);
String m3=m1+m2;
charInNote+=str.substring(note1, note3+2).length();
list.set(i, m3);
}else {
String rp=list.get(i);
rp=rp.replaceAll(dm, "");
list.set(i, rp);
}
}
return new long[]{countNote,charInNote};
}
}
InTotalCharsUtil
package cn.zg.utils;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class InTotalCharsUtil {
public static final String JAVA_SUFFIX=".java";
public static long javaCharsCount(String str) {
long count=0;
try(FileReader fileReader = new FileReader(new File(str))){
while(fileReader.read()!=-1){
count++;
}
}catch (IOException e){
e.printStackTrace();
}
return count;
}
public static long dirCharsCount(String dir) {
long count=0;
File file = new File(dir);
File[] files = file.listFiles((dir1,name)->
new File(dir1,name).isDirectory()||name.toLowerCase().endsWith(JAVA_SUFFIX));
if(files==null){
return 0;
}
for (File f : files) {
if(f.isFile()){
count+= javaCharsCount(f.getAbsolutePath());
}else{
count+= dirCharsCount(f.getAbsolutePath());
}
}
return count;
}
}
JavaFileCountUtil
package cn.zg.utils;
import java.io.File;
public class JavaFileCountUtil {
public static final String JAVA_SUFFIX=".java";
public static int javaFileCount(String str) {
int count=0;
File dir = new File(str);
File[] files = dir.listFiles((dir1,name)->
new File(dir1,name).isDirectory()||name.toLowerCase().endsWith(JAVA_SUFFIX));
if(files==null) {
return 0;
}
for (File f : files) {
if (f.isFile()){
count++;
}else{
count+=javaFileCount(f.getAbsolutePath());
}
}
return count;
}
}
KeySelectUtil
package cn.zg.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
public class KeySelectUtil {
public static final String[] KEYWORDS = {
"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", "short",
"static", "strictfp", "super", "switch", "synchronized", "this", "throw",
"throws", "transient", "try", "void", "volatile", "while"
};
public static final String END_OF_DOC="*/";
public static final String JAVA_SUFFIX=".java";
public static void matchKeywords(String line, Map<String,Integer> keywords) {
String[] wordList = line.replaceAll("\\W", " ").split(" ");
for (String s : wordList) {
for (String keyword : KEYWORDS) {
if (keyword.equals(s)) {
keywords.put(keyword, keywords.get(keyword)+1);
}
}
}
}
public static Map<String, Integer> fileCountKeyWords(String fileName) {
Map<String, Integer> keywords = new HashMap<>(50);
try (BufferedReader input = new BufferedReader(new FileReader(fileName))) {
for (String word : KEYWORDS) {
keywords.put(word,0);
}
String line;
while ((line = input.readLine()) != null) {
line = line.trim();
if (line.startsWith("//")) {
continue;
} else if (line.contains("/*")) {
if (!line.startsWith("/*")) {
matchKeywords(line, keywords);
}
while (!line.endsWith(END_OF_DOC)) {
String readLine = input.readLine();
if(readLine!=null){
line= readLine.trim();
}
}
}
matchKeywords(line,keywords);
}
}catch (IOException e){
e.printStackTrace();
}
return keywords;
}
public static Map<String, Integer> dirCountKeyWords(String fileName){
File file = new File(fileName);
File[] files = file.listFiles((dir1,name)->
new File(dir1,name).isDirectory()||name.toLowerCase().endsWith(JAVA_SUFFIX));
Map<String, Integer> keywords = new HashMap<>(50);
for (String word : KEYWORDS) {
keywords.put(word,0);
}
if(files==null){
return null;
}
for (File f : files) {
if(f.isFile()){
Map<String, Integer> map = fileCountKeyWords(f.getAbsoluteFile().toString());
for (String keyword : map.keySet()) {
keywords.put(keyword,keywords.get(keyword)+map.get(keyword));
}
}else{
Map<String, Integer> map = dirCountKeyWords(f.getAbsoluteFile().toString());
if (map != null) {
for (String keyword : map.keySet()) {
keywords.put(keyword,keywords.get(keyword)+map.get(keyword));
}
}
}
}
return keywords;
}
public static List<Map.Entry<String,Integer>> mapIntoListAndSort(Map<String, Integer> keywords){
List<Map.Entry<String,Integer>> list= new ArrayList<>(keywords.entrySet());
list.sort((o1, o2) -> {
if (o2.getValue().equals(o1.getValue())) {
return String.CASE_INSENSITIVE_ORDER.compare(o1.getKey(), o2.getKey());
}
return o2.getValue() - o1.getValue();
});
return list;
}
}
OtherUtils
package cn.zg.utils;
import cn.zg.frame.Start;
import java.util.Scanner;
public class OtherUtils {
public static void returnOrNotFile(String path){
System.out.println("文件分析结束, 分析结果存放在文件[data\\"+path+"]! ");
System.out.println();
System.out.println();
System.out.print("返回上一层请输入1,退出请输入0:");
boolean loop=true;
while(loop){
int input=new Scanner(System.in).nextInt();
if(input==1){
Start.mainFrame();
loop=false;
}else if(input==0){
loop=false;
System.exit(0);
}else{
System.out.print("输入有误!请重新输入!返回上一层请输入1,退出请输入0:");
}
}
}
public static void returnOrNotDir(String path){
System.out.println("目录分析结束, 分析结果存放在文件[data\\"+path+"]! ");
System.out.println();
System.out.println();
System.out.print("返回上一层请输入1,退出请输入0:");
boolean loop=true;
while(loop){
int input=new Scanner(System.in).nextInt();
if(input==1){
System.out.println();
System.out.println();
Start.mainFrame();
loop=false;
}else if(input==0){
loop=false;
System.exit(0);
}else{
System.out.print("输入有误!请重新输入!返回上一层请输入1,退出请输入0:");
}
}
}
}
TextIntoListUtil
package cn.zg.utils;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class TextIntoListUtil {
public static ArrayList<String> fileList(String filePath){
ArrayList<String> list = new ArrayList<>();
try(final BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath))){
String str;
while((str=bufferedReader.readLine())!=null){
list.add(str);
}
}catch (IOException e){
e.printStackTrace();
}
return list;
}
}
emm,只是格式要求有点烦人。
源码自取:
https://gitee.com/keepOrdinary/Comprehensive
|