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
() { - @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();
- }
- }