scau Java综合性实验之Java源程序分析程序
创始人
2024-02-04 23:53:51

1. 编写一个Java应用程序,实现对某个目录中的所有Java源程序文件(包含该目录的子目录中的源程序文件)进行统计。统计内容包括:

(1) 目录中每个源程序文件的总行数和空白行数,文件的字节数;

(2) 目录中所有源程序文件合计总行数、合计空白行数、合计文件的字节数。

2. 具体实现要求如下:

(1) 程序运行首先显示如下所示的菜单:

(2) 选择菜单中第1项时,要求输入一个目录名

如果输入目录名称对应的目录不存在或不是目录,则输出:

[目录名称] 不是合法的目录名称!

例如:

如果是合法存在的目录,则对该目录中的Java源程序文件进行分析,分析内容包括:

细节部分:每个源程序文件的行数、其中空行数、字节数。

合计部分:源程序文件个数、源程序文件行数、其中空行数、总的字节数。

注意,分析时包括输入目录中的所有子目录。

分析的结果的保存要求:

在当前项目目录中建立一个名为result的目录,结果文件存放在该目录中。

结果文件是一个文本文件,命名方式是用被分析的目录名作为主文件名,扩展名为目录名。

例如:分析D:demo目录,结果文件名为“demo.txt”。

结果文件中数据存放格式如下示例:

其中,

第1行:被分析目录的完整名称

第2行:空行

第3行:Files detail:

第4行:被分析目录的短名称,前面有一个 + 号

第5行:从本行开始依次输出被分析目录中的子目录和源程序文件

如果是子目录,则该行是 + 号 和 子目录的短名称

如果是源程序文件,则该行以 - 号开始,依次是:文件名、总行数、空白行数、字节数

注意:一个目录中如果既有子目录也有源程序文件,则先依次排列子目录,再依次排列文件。并且要按照名称升序排序。同时,每深入一层子目录,要缩进4个空格。

第X行:Total:

第X+1行:目录中总文件个数

第X+2行:目录中总的行数

第X+3行:目录中总的空白行数

第X+4行:目录中总字节数

(3) 选择菜单中第2项时,

如果result目录中还没有结果文件,则显示:还没有分析结果!

如果result目录中已经有结果文件,则以下面格式显示文件列表:

可以查看的结果文件有:

输入文件编号后,显示输出结果文件的内容,如果输入0表示不查看任何结果。编号输入错误应该提示。

这两天写综合性实验写的颇有感触……

emm…代码中有详细的注释,本人也比较菜,没用啥高深的算法,应该一看就会…

要是有啥不懂的可以私信问我呐

Menu类

package Project;import java.io.*;
import java.util.Scanner;public class Menu {private final Scanner Sc = new Scanner(System.in);//菜单public void showMenu() {System.out.println("----------MENU----------");System.out.println("1.分析目录中的源程序文件");System.out.println("2.查看分析结果");System.out.println("0.退出程序");System.out.println("------------------------");System.out.print("请选择:");chooseMenu();}//选择菜单的选项public void chooseMenu() {int choice;choice = Sc.nextInt();switch (choice) {case 1 -> {analyseFiles();break;}case 2 -> {checkResult();break;}case 0 -> {System.out.println("您已成功退出程序!");System.exit(0);}default -> System.out.println("您输入的选项有误!");}}//分析目录中的源程序文件private void analyseFiles() {System.out.println();System.out.print("请输入目录名称:");String FileName = Sc.next();Directory.root = new File(FileName);Directory.PathName = String.valueOf(new File(FileName));if (!Directory.root.isDirectory()) {System.out.println("错误:[" + Directory.root + "]不是目录名或不存在!\n");} else {Directory.outPut();System.out.println("分析成功!");}}private void checkResult() {System.out.println();File file = new File("Result");File[] files = file.listFiles();if (files == null) {System.out.println("还没有分析结果!");} else {System.out.println("--------------------------------");for (int i = 0; i < files.length; i++) {System.out.println(i + 1 + "." + files[i].getName());}System.out.println("--------------------------------");System.out.println("请选择要查看的结果文件(0表示放弃):");int choice = Sc.nextInt();if (choice == 0) {return;}if (choice > files.length) {System.out.print("您输入的选项有误!请重新输入:");checkResult();}System.out.println("查询结果如下:");checkFile(files[choice - 1]);//选项是比文件类数组大1的System.out.println();}}private void checkFile(File file) {BufferedReader br = null;try {br = new BufferedReader(new FileReader(file));while (true) {String data = br.readLine();if (data == null) {break;}System.out.println(data);}} catch (IOException e) {e.printStackTrace();} finally {{if (br != null) {try {br.close();} catch (IOException e) {e.printStackTrace();}}}}}
}

SourceFile类

package Project;import java.io.*;public class SourceFile {private File file;private long cntOfLines;//单个源码文件的行数private long cntOfBlank;//单个源码文件的空行数private long bytes;//单个源码文件的字节数public SourceFile(File file) {this.file = file;}//统计行数public long getCntOfLines() {//只有第一次调用才进行分析统计,节约时间if (cntOfLines == 0) {getCntOfLinesAndBlank();}return cntOfLines;}//统计空行数public long getCntOfBlank() {//同上if (cntOfBlank == 0) {getCntOfLinesAndBlank();}return cntOfBlank;}//统计字节数public long getBytes() {bytes = file.length();return bytes;}//统计行数和空行数public void getCntOfLinesAndBlank() {BufferedReader br = null;try {br = new BufferedReader(new FileReader(file));while (true) {String line = br.readLine();if (line == null) {break;}cntOfLines++;//每读一行,行数加一if ("".equals(line)) {cntOfBlank++;//读到空行,空行数加一}}} catch (IOException e) {e.printStackTrace();} finally {//关闭文件if (br != null) {try {br.close();} catch (IOException e) {e.printStackTrace();}}}}
}

Directory类

package Project;import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;public class Directory {static File root;//待分析的文件或文件夹static String PathName;//存放root路径/*static String dataPathName = "Result";//存储分析结果文件夹的路径static String testDataPath = "testData";//存放文件或文件夹的文件夹路径static File dataDir = new File(dataPathName);//存储分析结果文件夹的文件类static File testDir = new File(testDataPath);//存放测试文件或文件夹的文件夹的文件类*/static int level = 0;//用于记录递归的层数private static long AllOfLines;private static long AllOfBlank;private static long AllOfBytes;private static class GloBal {public static ArrayList fileArrayList = new ArrayList<>();//存放待分析的.java文件public static ArrayList outputData = new ArrayList<>();//存放分析结果的String}/*private static void saveFileList() {if (root.isDirectory()) {File[] files = root.listFiles();int len = files.length;for (int i = 0; i < len; i++) {if (files[i].isDirectory()) {root = files[i];saveFileList();} else {if (files[i].getName().endsWith(".java")) {//如果以.java结尾GloBal.fileArrayList.add(files[i]);//放入ArrayList中}}}}else if(root.isFile() && root.getName().endsWith(".java")){GloBal.fileArrayList.add(root);//放入ArrayList中}}*///开头格式private static void firstShow() {GloBal.outputData.add("[" + root.getAbsolutePath() + "]" + "  Result:");GloBal.outputData.add("");GloBal.outputData.add("Files detail:");}private static void saveFileList() {if (root.isDirectory()) {StringBuilder tapOfDirectory = getTap();GloBal.outputData.add(tapOfDirectory + "+" + root.getName());//目录File[] files = root.listFiles();//把root名下所有文件存进File[] files中int len = files.length;//root下文件或文件夹的个数//flag判断递归层数是否相同int flag = 0;for (int i = 0; i < len; i++) {//循环if (files[i].isDirectory()) {//如果是一个目录root = files[i];//更新root路径//递归层数相同时level只需要加一次if (flag == 0) {level++;flag = 1;}saveFileList();//递归 以存储.java文件} else {//如果不是一个目录(即是一个文件)if (files[i].getName().endsWith(".java")) {//如果以.java结尾//感觉好像没必要放进ArrayList//好吧好像有用,可以统计.java文件个数GloBal.fileArrayList.add(files[i]);//放入ArrayList中SourceFile SF = new SourceFile(files[i]);//使用SourceFile类进行统计//处理文件名 方面后面对齐StringBuilder newName = tidyFileName(files[i]);//处理Total,方便Blank对齐StringBuilder newTotal = tidyLines(files[i]);//处理Blank,方便bytes对齐StringBuilder newBlank = tidyBlank(files[i]);//字符数long bytes = SF.getBytes();StringBuilder tapOfFiles = getTap();GloBal.outputData.add(tapOfFiles+ "    -" + newName+ "\tTotal: " + newTotal+ "Blank: " + newBlank+ bytes + " bytes");/*GloBal.outputData.add("    -" + files[i].getName()+"\t\tTotal: " + SF.getCntOfLines()+ ",  Blank: " + SF.getCntOfBlank()+ ",  " + SF.getBytes() + " bytes");*///统计AllOfLines += SF.getCntOfLines();AllOfBlank += SF.getCntOfBlank();AllOfBytes += SF.getBytes();}}}} else if (root.isFile() && root.getName().endsWith(".java")) {//如果是文件且为.java文件则直接存储GloBal.fileArrayList.add(root);SourceFile SF = new SourceFile(root);StringBuilder newName = tidyFileName(root);StringBuilder newLines = tidyLines(root);StringBuilder newBlank = tidyBlank(root);GloBal.outputData.add("    -" + newName+ "\t Total:  " + newLines+ "Blank: " + newBlank+ SF.getBytes() + "  bytes");//统计AllOfLines += SF.getCntOfLines();AllOfBlank += SF.getCntOfBlank();AllOfBytes += SF.getBytes();}}//子目录比上一级缩进4格private static StringBuilder getTap() {StringBuilder tap = new StringBuilder();for (int i = 1; i <= level * 4; i++) {tap.append(" ");}return tap;}private static void saveTotal() {StringBuilder newCntOfFiles = tidyTotal(new StringBuilder(String.valueOf(getAllOfFiles())));StringBuilder newCntOfLines = tidyTotal(new StringBuilder(String.valueOf(getAllOfLines())));StringBuilder newCntOfBlank = tidyTotal(new StringBuilder(String.valueOf(getAllOfBlank())));StringBuilder newCntOfBytes = tidyTotal(new StringBuilder(String.valueOf(getAllOfBytes())));GloBal.outputData.add("Total:");GloBal.outputData.add("\t\t" + newCntOfFiles + "\tJava Files");GloBal.outputData.add("\t\t" + newCntOfLines + "\tlines in files");GloBal.outputData.add("\t\t" + newCntOfBlank + "\tblank lines");GloBal.outputData.add("\t\t" + newCntOfBytes + "\tbytes");}private static StringBuilder tidyTotal(StringBuilder str) {for (int i = str.length(); i < 8; i++) {str.append(" ");}return str;}private static StringBuilder tidyFileName(File file) {//处理文件名 方面后面对齐StringBuilder newName = new StringBuilder(file.getName());int size = file.getName().length();for (int j = size; j < 40; j++) {newName.append(" ");}return newName;}private static StringBuilder tidyLines(File file) {SourceFile SF = new SourceFile(file);//使用SourceFile类进行统计StringBuilder newLines = new StringBuilder(String.valueOf(SF.getCntOfLines()));int len = newLines.length();for (int j = len; j < 6; j++) {if (j == len) {newLines.append(",");}newLines.append(" ");}return newLines;}private static StringBuilder tidyBlank(File file) {SourceFile SF = new SourceFile(file);//使用SourceFile类进行统计StringBuilder newBlank = new StringBuilder(String.valueOf(SF.getCntOfBlank()));int lengthOfBlank = newBlank.length();for (int j = lengthOfBlank; j < 6; j++) {if (j == lengthOfBlank) {newBlank.append(",");}newBlank.append(" ");}return newBlank;}//对文件进行排序//这个可能有问题,后续要注意调试//如果一个目录里既有子目录又有文件,则先排子目录,再排文件private static void sortFiles(File[] files) {//使用匿名内部类构造比较器,对文件进行排序Arrays.sort(files, new Comparator() {@Overridepublic int compare(File o1, File o2) {if (o1.isFile() && o2.isFile()) {//都是文件return o1.getName().compareTo(o2.getName());} else if (o1.isDirectory() && o2.isDirectory()) {//都是目录return o1.getName().compareTo(o2.getName());} else if (o1.isDirectory() && o2.isFile()) {//一个目录一个文件return -1;} else if (o1.isFile() && o2.isDirectory()) {//一个文件一个目录return 1;} else {return 0;}}});}//统计.java文件个数public static int getAllOfFiles() {return GloBal.fileArrayList.size();}//统计所有.java文件中的字符个数/*private static void CountOfCharOfFile() {long SumOfChar = 0;for (int i = 0; i < GloBal.fileArrayList.size(); i++) {SumOfChar += GloBal.fileArrayList.get(i).length();}}*///统计总行数public static long getAllOfLines() {return AllOfLines;}//统计空行数public static long getAllOfBlank() {return AllOfBlank;}//统计字符数public static long getAllOfBytes() {return AllOfBytes;}/** 把分析结果保存到项目目录下的result文件夹* */public static void saveAnalyzeData() throws IOException {root = new File(PathName);//原输入的目录名称,在saveFileList经过递归后root不再是一开始的root了File resultFile = new File("Result");if (!resultFile.exists()) {resultFile.mkdir();}BufferedWriter AnalyzeDataIn = new BufferedWriter(new FileWriter(resultFile + "\\" + root.getName() + ".txt"));for (int i = 0; i < GloBal.outputData.size(); i++) {AnalyzeDataIn.write(GloBal.outputData.get(i));AnalyzeDataIn.newLine();}AnalyzeDataIn.flush();}/** 运行各方法以分析文件* 保存分析数据* */public static void outPut() {firstShow();saveFileList();saveTotal();try {saveAnalyzeData();} catch (IOException e) {e.printStackTrace();}}
}

Main类

package Project;public class Main {public static void main(String[] args) {run();}public static void run(){Menu menu = new Menu();menu.showMenu();run();}
}

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...