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

news2024/11/17 6:00:48

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/22726.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ADB调试--详细教程(附华为手机无法显示设备解决方法)

终端打开开发者模式&#xff0c;用数据线连接电脑&#xff0c;然后按照下面的步骤操作 1、开启开发者选项&#xff1a; 设置->关于设备->版本号&#xff08;连续点击5次&#xff09; 2、打开USB调试 在开发者选项中&#xff0c;找到USB调试&#xff0c;将此打开。 3、…

作为资深程序民工怎么能被性能优化难倒!原理与实战齐飞,源自大厂自然更专业!

性能优化是一个很复杂的工作&#xff0c;且充满了不确定性。它不像Java业务代码&#xff0c;可以一次编写到处运行(write once, run anywhere)&#xff0c;往往一些我们可能并不能察觉的变化&#xff0c;就会带来惊喜/惊吓。能够全面的了解并评估我们所负责应用的性能&#xff…

全渠道商城授权管控经销商,渠道商管理系统助力医药企业快速扩大渠道规模

随着医改的稳步推进&#xff0c;医药行业传统的以销售为主的扩张模式难以为继&#xff0c;国内药企面临创新转型。如何探寻医药数字化营销方法论&#xff0c;如何把握政策机遇和用户需求&#xff0c;利用数字化推动医药创新渠道破局&#xff0c;已成业内关注的重点。 后疫情时…

如何在win11中用双硬盘或移动硬盘装Ubuntu 20.04 双系统

首先明确一下思路&#xff0c;这个多硬盘的安装方式与单硬盘的方式没什么本质区别 下面介绍具体的方法&#xff1a; 1.下载Ubuntu系统镜像、制作系统盘 1.1 下载镜像 ubuntu20.04镜像下载&#xff1a;ubuntu20.04官网&#xff0c;点击进入下载 现在最新版是 Ubuntu 22.04.1…

ZX297520V3T:Codec NAU88C22驱动调试

一、音频驱动框架 ALSA(Advanced Linux Sound Architecture)是目前linux的主流音频体系结构。ALSA不仅在内核设备驱动层提供了alsa-driver,同时在应用层为我们提供了alsa-lib,应用程序只要调用alsa-lib提供的API,即可以完成对底层音频硬件的控制。为了方便调试,ALSA也提…

Spring~五种存储Bean对象的类注解、方法注解(@Bean)以及Bean对象的获取

目录 五种存储Bean对象的类注解 ​Controller Service Repository Component Configuration 方法注解Bean 使用Bean注解的常见问题 当一个类型有多个实例对象&#xff0c;使用类型获取就会报错 在容器中找不到Bean&#xff0c;不论通过什么方式来获取Bean对象都会报…

建设一个互联网医院系统要花多少钱?

建设一个互联网医院系统要花多少钱&#xff1f;很多人在筹备调研互联网医院建设后&#xff0c;仍然有很多问题答案不清楚&#xff0c;今天就给大家来聊一聊。 其实互联网医院看似简单&#xff0c;实则是一个较为复杂的过程&#xff0c;要想合法合规的开展线上诊疗业务&#x…

雷电模拟器dnconsole命令汇总

雷电模拟器之文件操作 删除相册中的文件 ldconsole adb --index 0 --command "shell rm /sdcard/DCIM/1.png" 雷电模拟器应用操作 假设启动名为test1的模拟器&#xff0c; 以抖音为例 &#xff1a; 判断应用是否安装&#xff1a; ldconsole adb --name test1 --co…

姿态识别+校准|视觉技术新突破

技术实现路径及优势 概述&#xff1a;通过2D图像序列加2D图像景深序列&#xff0c;利用复杂的3D重建算法与人体骨架模型的拟合还原姿态节点信息&#xff0c;进而对各种姿态进行准确的数学分析&#xff0c;达到准确高效识别姿态的效果&#xff1b;摆脱人脸3D训练样本真值依赖&am…

【输出重定向】Windows下 cmd 、powershell输出重定向

目录一、cmd和powershell二、什么是输入输出重定向三、语法及示例一、cmd和powershell 大家如果只用过Windows&#xff0c;可能cmd接触的相对多一点。按win r 输入cmd即可打开。我一般用的是powershell。 cmd:     cmd是command的缩写&#xff0c;即命令提示符。是提示命…

怎么手写转文字?借助这3款工具轻松实现

许多小伙伴在日常中会遇到需要把手写文字转换为电子版的情况&#xff0c;例如领导给一份手稿让你整理&#xff0c;亦或是平时自己随笔记录的一些内容想把它分享到平台上等等。但是手动逐字敲键盘输出太费时费神啦&#xff0c;所以今天要传授给大家一个好方法&#xff0c;那就是…

HTML5期末考核大作业,网站——青岛民俗 7页。 美丽家乡 学生旅行 游玩 主题住宿网页

&#x1f468;‍&#x1f393;静态网站的编写主要是用 HTML DⅣV CSSJS等来完成页面的排版设计&#x1f469;‍&#x1f393;&#xff0c;一般的网页作业需要融入以下知识点&#xff1a;div布局、浮动定位、高级css、表格、表单及验证、js轮播图、音频视频Fash的应用、uli、下拉…

LeetCode-808-分汤

1、动态规划法 我们可以利用二维数组dp[i][j]dp[i][j]dp[i][j]来记录当汤A的体积为i&#xff0c;汤B的体积为j时的概率。由于体积均为25的倍数&#xff0c;为了方便计算我们可以将所有体积都除以25。由于误差范围为10−510^{-5}10−5&#xff0c;我们可以计算得出当$n\ge179时…

Day08--自定义组件的插槽

1.什么是插槽 **************************************************************************************************************************************************************************************************************************** 2.单个插槽 我的操作&am…

一个小台灯 之 微信小程序开发日志

微信小程序开发日志 小程序只能使用https和后台服务器进行post请求和get请求&#xff0c;使用https的连接需要的微信小程序的后台对域名进行备份。 在备份的时候也只能通过域名&#xff0c;不能通过公网IP备份。 一、基础 微信小程序的一个界面主要分为四个文件 index.json…

剖析一下“抢茅台“脚本底层逻辑

本文作者&#xff1a;梁冬冬 前言&#xff1a; 今天你撸茅台了么&#x1f447;&#xff1f; 撸茅台已经成为社会现象&#x1f64c;&#xff0c;茶余饭后讨论的最佳实践&#x1f607; 2022年双十一大促已经完美收官&#xff0c;兄弟姐妹克服种种困难与挑战… 备战的会议室忙碌…

用户规模持续上涨,外卖行业未来的发展趋势如何?还能从里盈利?

外卖跑腿行业随着互联网移动支付及网络的普及得到了高速发展&#xff0c;相关数据显示2022年外卖行业规模进一步上升至8117亿元&#xff0c;外卖市场发展速度增速加快&#xff0c;并且也带动了各大主流外卖平台的发展&#xff0c;在2021年外卖用户规模达5.44亿人&#xff0c;占…

从工厂打螺丝到月薪9.5k测试工程师,我该满足吗?

以前我比较喜欢小米那句“永远相信美好的事情即将发生”&#xff0c;后来发现如果不努力不可能有美好的事情发生&#xff01; 初中毕业进厂5年&#xff0c;创业经商多次战败&#xff0c;为了生计辗转奔波 初中毕业后我就进了工厂&#xff0c;第一份工作是做模具加工。从500元一…

Python:用一行代码在几秒钟内抓取任何网站

如果你正在寻找最强大的 Python 抓取工具&#xff1f;不要再看了&#xff01;这一行代码将帮助你立即启动并运行。 Scrapeasy Scrapeasy 是一个 Python 库&#xff0c;可以轻松抓取网页并从中提取数据。它可用于从单个页面抓取数据或从多个页面抓取数据。它还可用于从 PDF 和 …

算法设计与分析 SCAU10346 带价值的作业安排问题

10346 带价值的作业安排问题 时间限制:1000MS 代码长度限制:10KB 提交次数:25 通过次数:9 题型: 编程题 语言: G;GCC;VC;JAVA Description 已知n项作业E{1, 2, … ,n} 需要完成&#xff0c;只有一台机器&#xff0c;同一时刻至多完成一个作业&#xff0c; 而且每项作业需要…