• scau Java综合性实验之Java源程序分析程序


    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类

    1. package Project;
    2. import java.io.*;
    3. import java.util.Scanner;
    4. public class Menu {
    5. private final Scanner Sc = new Scanner(System.in);
    6. //菜单
    7. public void showMenu() {
    8. System.out.println("----------MENU----------");
    9. System.out.println("1.分析目录中的源程序文件");
    10. System.out.println("2.查看分析结果");
    11. System.out.println("0.退出程序");
    12. System.out.println("------------------------");
    13. System.out.print("请选择:");
    14. chooseMenu();
    15. }
    16. //选择菜单的选项
    17. public void chooseMenu() {
    18. int choice;
    19. choice = Sc.nextInt();
    20. switch (choice) {
    21. case 1 -> {
    22. analyseFiles();
    23. break;
    24. }
    25. case 2 -> {
    26. checkResult();
    27. break;
    28. }
    29. case 0 -> {
    30. System.out.println("您已成功退出程序!");
    31. System.exit(0);
    32. }
    33. default -> System.out.println("您输入的选项有误!");
    34. }
    35. }
    36. //分析目录中的源程序文件
    37. private void analyseFiles() {
    38. System.out.println();
    39. System.out.print("请输入目录名称:");
    40. String FileName = Sc.next();
    41. Directory.root = new File(FileName);
    42. Directory.PathName = String.valueOf(new File(FileName));
    43. if (!Directory.root.isDirectory()) {
    44. System.out.println("错误:[" + Directory.root + "]不是目录名或不存在!\n");
    45. } else {
    46. Directory.outPut();
    47. System.out.println("分析成功!");
    48. }
    49. }
    50. private void checkResult() {
    51. System.out.println();
    52. File file = new File("Result");
    53. File[] files = file.listFiles();
    54. if (files == null) {
    55. System.out.println("还没有分析结果!");
    56. } else {
    57. System.out.println("--------------------------------");
    58. for (int i = 0; i < files.length; i++) {
    59. System.out.println(i + 1 + "." + files[i].getName());
    60. }
    61. System.out.println("--------------------------------");
    62. System.out.println("请选择要查看的结果文件(0表示放弃):");
    63. int choice = Sc.nextInt();
    64. if (choice == 0) {
    65. return;
    66. }
    67. if (choice > files.length) {
    68. System.out.print("您输入的选项有误!请重新输入:");
    69. checkResult();
    70. }
    71. System.out.println("查询结果如下:");
    72. checkFile(files[choice - 1]);//选项是比文件类数组大1的
    73. System.out.println();
    74. }
    75. }
    76. private void checkFile(File file) {
    77. BufferedReader br = null;
    78. try {
    79. br = new BufferedReader(new FileReader(file));
    80. while (true) {
    81. String data = br.readLine();
    82. if (data == null) {
    83. break;
    84. }
    85. System.out.println(data);
    86. }
    87. } catch (IOException e) {
    88. e.printStackTrace();
    89. } finally {
    90. {
    91. if (br != null) {
    92. try {
    93. br.close();
    94. } catch (IOException e) {
    95. e.printStackTrace();
    96. }
    97. }
    98. }
    99. }
    100. }
    101. }

    SourceFile类

    1. package Project;
    2. import java.io.*;
    3. public class SourceFile {
    4. private File file;
    5. private long cntOfLines;//单个源码文件的行数
    6. private long cntOfBlank;//单个源码文件的空行数
    7. private long bytes;//单个源码文件的字节数
    8. public SourceFile(File file) {
    9. this.file = file;
    10. }
    11. //统计行数
    12. public long getCntOfLines() {
    13. //只有第一次调用才进行分析统计,节约时间
    14. if (cntOfLines == 0) {
    15. getCntOfLinesAndBlank();
    16. }
    17. return cntOfLines;
    18. }
    19. //统计空行数
    20. public long getCntOfBlank() {
    21. //同上
    22. if (cntOfBlank == 0) {
    23. getCntOfLinesAndBlank();
    24. }
    25. return cntOfBlank;
    26. }
    27. //统计字节数
    28. public long getBytes() {
    29. bytes = file.length();
    30. return bytes;
    31. }
    32. //统计行数和空行数
    33. public void getCntOfLinesAndBlank() {
    34. BufferedReader br = null;
    35. try {
    36. br = new BufferedReader(new FileReader(file));
    37. while (true) {
    38. String line = br.readLine();
    39. if (line == null) {
    40. break;
    41. }
    42. cntOfLines++;//每读一行,行数加一
    43. if ("".equals(line)) {
    44. cntOfBlank++;//读到空行,空行数加一
    45. }
    46. }
    47. } catch (IOException e) {
    48. e.printStackTrace();
    49. } finally {//关闭文件
    50. if (br != null) {
    51. try {
    52. br.close();
    53. } catch (IOException e) {
    54. e.printStackTrace();
    55. }
    56. }
    57. }
    58. }
    59. }

    Directory类

    1. package Project;
    2. import java.io.BufferedWriter;
    3. import java.io.File;
    4. import java.io.FileWriter;
    5. import java.io.IOException;
    6. import java.util.ArrayList;
    7. import java.util.Arrays;
    8. import java.util.Comparator;
    9. public class Directory {
    10. static File root;//待分析的文件或文件夹
    11. static String PathName;//存放root路径
    12. /*static String dataPathName = "Result";//存储分析结果文件夹的路径
    13. static String testDataPath = "testData";//存放文件或文件夹的文件夹路径
    14. static File dataDir = new File(dataPathName);//存储分析结果文件夹的文件类
    15. static File testDir = new File(testDataPath);//存放测试文件或文件夹的文件夹的文件类*/
    16. static int level = 0;//用于记录递归的层数
    17. private static long AllOfLines;
    18. private static long AllOfBlank;
    19. private static long AllOfBytes;
    20. private static class GloBal {
    21. public static ArrayList fileArrayList = new ArrayList<>();//存放待分析的.java文件
    22. public static ArrayList outputData = new ArrayList<>();//存放分析结果的String
    23. }
    24. /*
    25. private static void saveFileList() {
    26. if (root.isDirectory()) {
    27. File[] files = root.listFiles();
    28. int len = files.length;
    29. for (int i = 0; i < len; i++) {
    30. if (files[i].isDirectory()) {
    31. root = files[i];
    32. saveFileList();
    33. } else {
    34. if (files[i].getName().endsWith(".java")) {//如果以.java结尾
    35. GloBal.fileArrayList.add(files[i]);//放入ArrayList中
    36. }
    37. }
    38. }
    39. }else if(root.isFile() && root.getName().endsWith(".java")){
    40. GloBal.fileArrayList.add(root);//放入ArrayList中
    41. }
    42. }
    43. */
    44. //开头格式
    45. private static void firstShow() {
    46. GloBal.outputData.add("[" + root.getAbsolutePath() + "]" + " Result:");
    47. GloBal.outputData.add("");
    48. GloBal.outputData.add("Files detail:");
    49. }
    50. private static void saveFileList() {
    51. if (root.isDirectory()) {
    52. StringBuilder tapOfDirectory = getTap();
    53. GloBal.outputData.add(tapOfDirectory + "+" + root.getName());//目录
    54. File[] files = root.listFiles();//把root名下所有文件存进File[] files中
    55. int len = files.length;//root下文件或文件夹的个数
    56. //flag判断递归层数是否相同
    57. int flag = 0;
    58. for (int i = 0; i < len; i++) {//循环
    59. if (files[i].isDirectory()) {//如果是一个目录
    60. root = files[i];//更新root路径
    61. //递归层数相同时level只需要加一次
    62. if (flag == 0) {
    63. level++;
    64. flag = 1;
    65. }
    66. saveFileList();//递归 以存储.java文件
    67. } else {//如果不是一个目录(即是一个文件)
    68. if (files[i].getName().endsWith(".java")) {//如果以.java结尾
    69. //感觉好像没必要放进ArrayList
    70. //好吧好像有用,可以统计.java文件个数
    71. GloBal.fileArrayList.add(files[i]);//放入ArrayList中
    72. SourceFile SF = new SourceFile(files[i]);//使用SourceFile类进行统计
    73. //处理文件名 方面后面对齐
    74. StringBuilder newName = tidyFileName(files[i]);
    75. //处理Total,方便Blank对齐
    76. StringBuilder newTotal = tidyLines(files[i]);
    77. //处理Blank,方便bytes对齐
    78. StringBuilder newBlank = tidyBlank(files[i]);
    79. //字符数
    80. long bytes = SF.getBytes();
    81. StringBuilder tapOfFiles = getTap();
    82. GloBal.outputData.add(tapOfFiles
    83. + " -" + newName
    84. + "\tTotal: " + newTotal
    85. + "Blank: " + newBlank
    86. + bytes + " bytes");
    87. /*GloBal.outputData.add(" -" + files[i].getName()
    88. +"\t\tTotal: " + SF.getCntOfLines()
    89. + ", Blank: " + SF.getCntOfBlank()
    90. + ", " + SF.getBytes() + " bytes");*/
    91. //统计
    92. AllOfLines += SF.getCntOfLines();
    93. AllOfBlank += SF.getCntOfBlank();
    94. AllOfBytes += SF.getBytes();
    95. }
    96. }
    97. }
    98. } else if (root.isFile() && root.getName().endsWith(".java")) {//如果是文件且为.java文件则直接存储
    99. GloBal.fileArrayList.add(root);
    100. SourceFile SF = new SourceFile(root);
    101. StringBuilder newName = tidyFileName(root);
    102. StringBuilder newLines = tidyLines(root);
    103. StringBuilder newBlank = tidyBlank(root);
    104. GloBal.outputData.add(" -" + newName
    105. + "\t Total: " + newLines
    106. + "Blank: " + newBlank
    107. + SF.getBytes() + " bytes");
    108. //统计
    109. AllOfLines += SF.getCntOfLines();
    110. AllOfBlank += SF.getCntOfBlank();
    111. AllOfBytes += SF.getBytes();
    112. }
    113. }
    114. //子目录比上一级缩进4格
    115. private static StringBuilder getTap() {
    116. StringBuilder tap = new StringBuilder();
    117. for (int i = 1; i <= level * 4; i++) {
    118. tap.append(" ");
    119. }
    120. return tap;
    121. }
    122. private static void saveTotal() {
    123. StringBuilder newCntOfFiles = tidyTotal(new StringBuilder(String.valueOf(getAllOfFiles())));
    124. StringBuilder newCntOfLines = tidyTotal(new StringBuilder(String.valueOf(getAllOfLines())));
    125. StringBuilder newCntOfBlank = tidyTotal(new StringBuilder(String.valueOf(getAllOfBlank())));
    126. StringBuilder newCntOfBytes = tidyTotal(new StringBuilder(String.valueOf(getAllOfBytes())));
    127. GloBal.outputData.add("Total:");
    128. GloBal.outputData.add("\t\t" + newCntOfFiles + "\tJava Files");
    129. GloBal.outputData.add("\t\t" + newCntOfLines + "\tlines in files");
    130. GloBal.outputData.add("\t\t" + newCntOfBlank + "\tblank lines");
    131. GloBal.outputData.add("\t\t" + newCntOfBytes + "\tbytes");
    132. }
    133. private static StringBuilder tidyTotal(StringBuilder str) {
    134. for (int i = str.length(); i < 8; i++) {
    135. str.append(" ");
    136. }
    137. return str;
    138. }
    139. private static StringBuilder tidyFileName(File file) {
    140. //处理文件名 方面后面对齐
    141. StringBuilder newName = new StringBuilder(file.getName());
    142. int size = file.getName().length();
    143. for (int j = size; j < 40; j++) {
    144. newName.append(" ");
    145. }
    146. return newName;
    147. }
    148. private static StringBuilder tidyLines(File file) {
    149. SourceFile SF = new SourceFile(file);//使用SourceFile类进行统计
    150. StringBuilder newLines = new StringBuilder(String.valueOf(SF.getCntOfLines()));
    151. int len = newLines.length();
    152. for (int j = len; j < 6; j++) {
    153. if (j == len) {
    154. newLines.append(",");
    155. }
    156. newLines.append(" ");
    157. }
    158. return newLines;
    159. }
    160. private static StringBuilder tidyBlank(File file) {
    161. SourceFile SF = new SourceFile(file);//使用SourceFile类进行统计
    162. StringBuilder newBlank = new StringBuilder(String.valueOf(SF.getCntOfBlank()));
    163. int lengthOfBlank = newBlank.length();
    164. for (int j = lengthOfBlank; j < 6; j++) {
    165. if (j == lengthOfBlank) {
    166. newBlank.append(",");
    167. }
    168. newBlank.append(" ");
    169. }
    170. return newBlank;
    171. }
    172. //对文件进行排序
    173. //这个可能有问题,后续要注意调试
    174. //如果一个目录里既有子目录又有文件,则先排子目录,再排文件
    175. private static void sortFiles(File[] files) {
    176. //使用匿名内部类构造比较器,对文件进行排序
    177. Arrays.sort(files, new Comparator() {
    178. @Override
    179. public int compare(File o1, File o2) {
    180. if (o1.isFile() && o2.isFile()) {//都是文件
    181. return o1.getName().compareTo(o2.getName());
    182. } else if (o1.isDirectory() && o2.isDirectory()) {//都是目录
    183. return o1.getName().compareTo(o2.getName());
    184. } else if (o1.isDirectory() && o2.isFile()) {//一个目录一个文件
    185. return -1;
    186. } else if (o1.isFile() && o2.isDirectory()) {//一个文件一个目录
    187. return 1;
    188. } else {
    189. return 0;
    190. }
    191. }
    192. });
    193. }
    194. //统计.java文件个数
    195. public static int getAllOfFiles() {
    196. return GloBal.fileArrayList.size();
    197. }
    198. //统计所有.java文件中的字符个数
    199. /*private static void CountOfCharOfFile() {
    200. long SumOfChar = 0;
    201. for (int i = 0; i < GloBal.fileArrayList.size(); i++) {
    202. SumOfChar += GloBal.fileArrayList.get(i).length();
    203. }
    204. }*/
    205. //统计总行数
    206. public static long getAllOfLines() {
    207. return AllOfLines;
    208. }
    209. //统计空行数
    210. public static long getAllOfBlank() {
    211. return AllOfBlank;
    212. }
    213. //统计字符数
    214. public static long getAllOfBytes() {
    215. return AllOfBytes;
    216. }
    217. /*
    218. * 把分析结果保存到项目目录下的result文件夹
    219. * */
    220. public static void saveAnalyzeData() throws IOException {
    221. root = new File(PathName);//原输入的目录名称,在saveFileList经过递归后root不再是一开始的root了
    222. File resultFile = new File("Result");
    223. if (!resultFile.exists()) {
    224. resultFile.mkdir();
    225. }
    226. BufferedWriter AnalyzeDataIn = new BufferedWriter
    227. (new FileWriter(resultFile + "\\" + root.getName() + ".txt"));
    228. for (int i = 0; i < GloBal.outputData.size(); i++) {
    229. AnalyzeDataIn.write(GloBal.outputData.get(i));
    230. AnalyzeDataIn.newLine();
    231. }
    232. AnalyzeDataIn.flush();
    233. }
    234. /*
    235. * 运行各方法以分析文件
    236. * 保存分析数据
    237. * */
    238. public static void outPut() {
    239. firstShow();
    240. saveFileList();
    241. saveTotal();
    242. try {
    243. saveAnalyzeData();
    244. } catch (IOException e) {
    245. e.printStackTrace();
    246. }
    247. }
    248. }

    Main类

    1. package Project;
    2. public class Main {
    3. public static void main(String[] args) {
    4. run();
    5. }
    6. public static void run(){
    7. Menu menu = new Menu();
    8. menu.showMenu();
    9. run();
    10. }
    11. }

  • 相关阅读:
    Matlab 对连续时间信号的运算
    CamVid数据集--学习笔记
    使用i18n Ayll在项目中也能显示中文
    领域驱动设计——领域的重构
    mysql的常见的外键约束
    儿童用台灯用白光好还是暖光好?推荐儿童使用的暖光台灯
    golang 琐碎知识
    [android毕业设计源码]精品基于Uniapp实现的美食APP[安卓毕业设计]
    移动宣传舞台车设计及运动仿真(lunwen+开题报告+初稿+cad图纸)
    【李航统计学习笔记】第二章:感知机
  • 原文地址:https://blog.csdn.net/zqihm/article/details/127953616