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<File> fileArrayList = new ArrayList<>();//存放待分析的.java文件
public static ArrayList<String> 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<File>() {
@Override
public 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();
}
}