SCAU综合性实验 Java 源代码注释及关键字分析程序 (附类图)

SCAU综合性实验 Java 源代码注释及关键字分析程序 (附类图)

题目:

类别: D 综合性实验

关键字: 类、对象、封装、聚合、组合、继承、IO

内容要求:

一、实验目的

(1)掌握面向对象程序设计的基本方法

(2)应用 Java 语言编写应用程序

二、实验内容 编写一个 Java 应用程序,对单个 Java 源程序文件及某个目录中的所有 Java 源程序文件(包括子目录)进 行分析,分析内容包括:

Java 源程序文件个数,对目录分析进行分析时需要。

Java 源程序中的字符个数,对目录分析时是其中所有源程序文件的字符个数总和。

Java 源程序文件中的注释的个数,即源程序文件中共有多少个注释,包括:单行注释和多行注释。对目录 分析时是其中所有源程序文件的总和。

Java 源程序文件中的注释的字符个数,即源程序文件中所有注释的字符数之和。对目录分析时是其中所有 源程序文件的总和。

Java 源程序文件中关键字使用情况,即源程序文件各个关键字使用了多少次。对目录分析时是其中所有源 程序文件的总和。

具体要求如下:

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

2.分析目录或源程序文件要求

选择菜单项目 1 时,首先要求输入要分析的目录名或 Java 源程序文件名。 如果输入的目录或文件名不存在,提示不存在;输入的文件名的扩展名不是“.java”时提示不是 Java 源 程序文件。 如果输入的是一个 Java 源程序文件名,对该源程序文件进行分析。 如果输入的是一个目录名,对该目录中所有的源程序文件进行分析。 分析的结果存储到一个文本文件中,在当前目录中建立一个 data 目录,结果文件放在 data 目录中。 分析目录时结果文件名:D_目录名_Result.txt,例如:D_lang_Result.txt 分析源程序文件时结果文件名:F_源程序文件名_Result.txt,

例如:F_String.java_Result.txt 结果文件中内容的格式:

第 1 行:分析目录 : C:\Program Files\Java\jdk1.8.0_31\src\java

第 2 行:空行

第 3 行:Java 源程序文件个数: 1866 (分析文件时无此行)

第 4 行:源程序中字符总个数 : 29022541

第 5 行:注释总个数 : 57349

第 6 行:注释总的字符数 : 17559371

第 7 行:空行

第 8 行:关键字使用情况如下:

第 9 行:[int = 27705] (从第 9 行开始输出各个关键字及其使用的次数,每行一个)

说明: 分析结束时,不显示分析结果,结果存储到文本文件,显示如下提示: 目录分析结束, 分析结果存放在文件[data/D_util_Result.txt]! 或者: 文件分析结束, 分析结果存放在文件[data/F_String.java_Result.txt]! 关键字输出时,按使用次数从大到小排序,次数相同时,按字母顺序排序。

// Java 语言的所有关键字 public static final String[] KEYWORDS = { “abstract”, “assert”, “boolean”, “break”, “byte”, “case”, “catch”, “char”, “class”, “const”, “continue”, “default”, “do”, “double”, “else”, “enum”, “extends”, “final”, “finally”, “float”, “for”, “goto”, “if”, “implements”, “import”, “instanceof”, “int”, “interface”, “long”, “native”, “new”, “package”, “private”, “protected”, “public”, “return”, “short”, “static”, “strictfp”, “super”, “switch”, “synchronized”, “this”, “throw”, “throws”, “transient”, “try”, “void”, “volatile”, “while” };

2.查看已有的分析结果要求 选择菜单项目 2 时,首先列出已经分析并存储的结果,如下图:

即列出 data 目录中存储的所有分析结果文件,并给出一个序号。 输入要查看的文件序号后,显示该文件中的内容。例如下图:

三、实验完成提示

1.分析注释个数和注释的字符数时,假设没有注释嵌套的问题。即测试用的文件和目录中没有如下情况: /** //注释 1 / // 注释 2 / */ *

*2.分析注释个数和注释的字符数时,假设字符串直接量中没有注释形式,即没有下面的情况: String s = “/abcd/”;

3.分析关键字使用次数时,注意以下几种情况不能计算关键字个数:

(1) 注释中出现的关键字,例如下面的 int 不能计数 /** * int k=0; */

(2) 字符串直接量中的关键字,例如下面的 int 不能计数 System.out.println(“input a int: ”);

(3) 注意整字识别,例如 println 中的 int 不是关键字,不能计数。

4.如果使用正则表达式进行编程,除基本的正则表达式使用外,可以参考 Java 的如下两个类: java.util.regex.Pattern java.util.regex.Matcher

代码:这里分了五个类以及一个接口

第一个类:Main类(主函数)

作用:主函数,可以调用其它的功能(具体见注释)

代码:

package finalExam;

import java.io.*;
import java.util.Scanner;

public class Main {
    private static String addressList;//用于存储输入的路径

    public static String getAddressList() {
        return addressList;
    }

    public static void setAddressList(String addressList) {
        Main.addressList = addressList;
    }

    //主函数
    public static void main(String[] args) throws IOException {

        Scanner scanner = new Scanner(System.in);
        while (true) {//循环至退出
            menu();
            int choose = scanner.nextInt();
            switch (choose) {//选择
                case 1: {
                    System.out.println("请输入:");
                    String str = scanner.next();
                    AnalyseDir analyseDir = new AnalyseDir(str);//创建analyseDir对象
                    File f = new File(str);
                    if (str.contains(".java")) {
                        addressList = str;
                        analyseDir.programData();
                    } else if (!f.exists()) {
                        System.out.println("不存在此目录或文件名");
                    } else if (f.isDirectory()) {
                        addressList = str;
                        analyseDir.documentData();
                    } else System.out.println("不是 Java 源程序文件");
                    break;
                }
                case 2: {
                    ScanResult.menu2();
                    break;
                }
                case 0:
                    return;
            }
//            scanner.close();
        }
    }

    public static void menu() {//主界面
        System.out.println("-------MENU-------");
        System.out.println(" 1.分析目录或源程序文件");
        System.out.println(" 2.查看已有的分析结果");
        System.out.println(" 0.退出");
        System.out.println("------------------");
        System.out.println("请选择:");
    }

}

第二个类:AnalyseDir

作用:分析输入的路径,分别对目录名以及文件名进行分析

代码:

package finalExam;

import java.io.*;
import java.util.List;
import java.util.Objects;

public class AnalyseDir extends Main implements CorrectRoad {

    static String sdir = "data";

    private String str;

    //有参构造
    public AnalyseDir(String str) {
        this.str = str;
    }

    //封装
    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }


    public void programData() throws IOException {//源程序文件

        try (
                FileReader fr = new FileReader(str);
                BufferedReader bfr = new BufferedReader(fr)//用缓冲读取
        ) {
            int sum = 0;
            while (bfr.read() != -1) {//统计字符数
                sum++;
            }

            //对路径进行处理
            int i = CorrectRoad.nameWhere(str);
            String str3 = str.substring(i + 1);
            String str2 = str.substring(0, i);
            i = CorrectRoad.nameWhere(str2);//第二个/
            String str1 = str.substring(0, i+1);
            File fdir = new File(str1 + sdir);
            String last = "F_" + str3 + "_Result.txt";
            File fdir2 = new File(str1 + sdir + "/" + last);
            if (!fdir.isDirectory()) {
                fdir.mkdir();
                fdir2.createNewFile(); // 创建新文件
            } else if (!fdir2.exists()) {
                fdir2.createNewFile(); // 创建新文件
            }

            List list = TheKeyWord.makeMap(str);
            BufferedWriter bw = new BufferedWriter(new FileWriter(fdir2));//用缓冲写入
            SearchAnnotation searchAnnotation = new SearchAnnotation(str);
            try {
                bw.write(
                        "------------------------------------------------------------------\n" +
                                "分析目录 :" + str + "\n" +
                                "\n" +
                                "源程序中字符总个数 : " + sum + "\n" +
                                "注释总个数 : " + searchAnnotation.search(0) + "\n" +
                                "注释总的字符数 : " + searchAnnotation.search(1) + "\n" +
                                "\n" +
                                "关键字使用情况如下:\n");
                for (Object o : list) {
                    bw.write(
                            "[" + o + "] \n");
                }
                bw.write(
                        "------------------------------------------------------------------");
            } catch (Exception e) {
                e.printStackTrace();
            }

            bw.flush();

            System.out.println("文件分析结束, 分析结果存放在文件[data/F_" + str3 + "_Result.txt]!");
        }
    }

    public void documentData() throws IOException {//目录

        int count = 0, sum1 = 0, sum2 = 0, sum3 = 0;//用于累加
        File fdir0 = new File(str);
        for (int i = 0; i < Objects.requireNonNull(fdir0.list()).length; i++) {
            if (Objects.requireNonNull(fdir0.list())[i].contains(".java")) {
                String strAddress = str + "/" + Objects.requireNonNull(fdir0.list())[i];
                SearchAnnotation searchAnnotation = new SearchAnnotation(strAddress);

                try {
                    FileReader fr = new FileReader(strAddress);
                    BufferedReader br1 = new BufferedReader(fr);
                    while (br1.read() != -1) {//统计字符数
                        sum3++;
                    }
                    sum1 += searchAnnotation.search(0);//注释总个数
                    sum2 += searchAnnotation.search(1);//注释总的字符数
                } catch (Exception e) {
                    e.printStackTrace();
                }
                count++;
            }
        }

        //对路径进行处理
        int j = CorrectRoad.nameWhere(str);
        String str3 = str.substring(j + 1);
        String str1 = str.substring(0, j + 1);
        File fdir = new File(str1 + sdir);
        String last = "D_" + str3 + "_Result.txt";
        File fdir2 = new File(str1 + "/" + sdir + "/" + last);
        if (!fdir.isDirectory()) {
            fdir.mkdir();
            fdir2.createNewFile(); // 创建新文件
        } else if (!fdir2.exists()) {
            fdir2.createNewFile(); // 创建新文件
        }

        List list = TheKeyWord.makeMap(str);
        BufferedWriter bw = new BufferedWriter(new FileWriter(fdir2));//用缓冲写入
        bw.write(
                "------------------------------------------------------------------\n" +
                        "分析目录 : " + str + "\n" +
                        "\n" +
                        "Java 源程序文件个数: " + count + " \n" +
                        "源程序中字符总个数 : " + sum3 + "\n" +
                        "注释总个数 : " + sum1 + "\n" +
                        "注释总的字符数 : " + sum2 + "\n" +
                        "\n" +
                        "关键字使用情况如下:\n");
        for (Object o : list) {
            bw.write(
                    "[" + o + "] \n");
        }
        bw.write(
                "------------------------------------------------------------------");
        bw.flush();

        System.out.println("目录分析结束, 分析结果存放在文件[data/D_" + str3 + "_Result.txt]!");
    }

}

第三个类:ScanResult

作用:对主菜单中选项2的功能实现

代码:

package finalExam;

import java.io.*;
import java.util.Objects;
import java.util.Scanner;

public class ScanResult extends Main implements CorrectRoad {

    public static void showResult(File f, int n) throws IOException {

        String str;
        try (//用缓冲读取
             FileReader fr = new FileReader(f.getPath()+'/'+ Objects.requireNonNull(f.list())[n - 1]);
             BufferedReader bfr = new BufferedReader(fr)
        ) {
            while ((str = bfr.readLine()) != null) {//输出文件内容
                System.out.println(str);
            }
        }
    }

    public static void menu2() throws IOException {//查看已有的分析结果界面
        String str;
        String str0 = getAddressList();
        if(str0.contains(".java")){
            int i = CorrectRoad.nameWhere(str0);
            String str2 = str0.substring(0, i);
            i = CorrectRoad.nameWhere(str2);
            String str3 = str2.substring(0, i);
            str = str3 + "/data";
        }else{
            String str1 = str0.substring(0, CorrectRoad.nameWhere(str0));//调整为可读路径
            str = str1 + "/data";
        }
        Scanner scanner = new Scanner(System.in);
        File f = new File(str);
        System.out.println("--------------------------------------------");
        for (int i = 1; i <= Objects.requireNonNull(f.list()).length && Objects.requireNonNull(f.list())[i - 1] != null; i++) {
            System.out.println("   " + i + " -- " + Objects.requireNonNull(f.list())[i - 1]);
        }
        System.out.println("--------------------------------------------");
        System.out.println("输入要查看的文件的编号:");
        int choose2 = scanner.nextInt();
        showResult(f,choose2);
    }
}

第四个类:SearchAnnotation

这里是唯一一个参考其它大佬的代码,因为自己敲了很久,还是敲不出来。

作用:寻找注释

代码:

package finalExam;

import java.io.*;
import java.util.ArrayList;

public class SearchAnnotation extends AnalyseDir {

    //有参构造
    public SearchAnnotation(String str) {
        super(str);
    }

    public int search(int n) throws Exception {
        ArrayList<String> ve = new ArrayList<>();
        try (//用缓冲读取
                FileReader fr = new FileReader(super.getStr());
                BufferedReader bfr = new BufferedReader(fr)
        ) {

            String s;
            while ((s = bfr.readLine()) != null) {//使用readLine方法,一次读一行
                ve.add(s);
            }
        }
        if (n == 0) return operateNote(ve)[0];
        else return operateNote(ve)[1];
    }

    public static int[] operateNote(ArrayList<String> list) throws IOException {

        String s;
        int countNote = 0;
        int charInNote = 0;
        for (int j = 0; j < list.size(); j++) {
            s = list.get(j);
            int note1 = s.indexOf("/*");
            int note2 = s.indexOf("//");
            int note3 = s.indexOf("*/");
            //int note4=s.indexOf("\"");
            String dm = "\"(.*)\"";//双引号
            String sm = "\'(.*)\'";//单引号

            if (note1 != -1 && note3 == -1) {//多行注释
                countNote++;
                String ttt = list.get(j);
                list.set(j, ttt.substring(0, note1));
                charInNote += s.substring(note1).length() + 1;//+1是包括换行符

                s = list.get(++j);
                while ((note3 = s.indexOf("*/")) == -1) {
                    if ((note2 = s.indexOf("//")) != -1) {
                        countNote++;
                    }
                    list.remove(j);

                    charInNote += s.length() + 1;
                    if (j < list.size() - 1) {
                        s = list.get(++j);
                    } else {
                        break;
                    }
                }
                list.set(j, "");
                charInNote += s.length();

            } else if (note2 != -1) {// "//"类的单行注释
                countNote++;
                list.set(j, s.substring(0, note2));
                charInNote += s.substring(note2).length() + 1;
            } else if (note1 != -1 && note3 != -1) {//单行注释
                countNote++;

                String m1 = s.substring(0, note1);
                String m2 = s.substring(note3 + 2);
                String m3 = m1 + m2;
                charInNote += s.substring(note1, note3 + 2).length();
                list.set(j, m3);
            } else {//删除输出语句
                String rp = list.get(j);
                rp = rp.replaceAll(dm, "");
                list.set(j, rp);
            }
        }
        return new int[]{countNote, charInNote};
    }
}


第五个类:TheKeyWord

这里是自己敲出来的,没有用到正则表达式,纯想!

作用:寻找50个java的关键词

代码:

package finalExam;

import java.io.*;
import java.util.*;

public class TheKeyWord extends AnalyseDir {

    public static final String[] KEYWORDS = {"abstract", "assert", "boolean", "break", "byte", "case",
            "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum",
            "extends", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof",
            "int", "interface", "long", "native", "new", "package", "private", "protected", "public",
            "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw",
            "throws", "transient", "try", "void", "volatile", "while"};//50个关键字词

    //有参构造
    public TheKeyWord(String str) {
        super(str);
    }

    public static void check(Map<String, Integer>map, String str) throws IOException {
        try (
                FileReader fr = new FileReader(str);
                BufferedReader bfr = new BufferedReader(fr)
        ) {
            String s, s1;
            int is = 1;
            while ((s1 = bfr.readLine()) != null) {//使用readLine方法,一次读一行
                //对注释
                if (s1.contains("/**") && is == 1) {
                    is = 0;
                }else if(s1.contains("*/")){
                    is = 1;
                }else if(is == 0 && s1.contains("*")){
                }else if(is == 1) {
                    for (Map.Entry<String, Integer> entry : map.entrySet()) {
                        s = s1;
                        while (s.contains(entry.getKey())) {
                            //对复合词
                            if (((s.indexOf(entry.getKey()) != 0) && (s.charAt(s.indexOf(entry.getKey()) - 1) != ' ')) || ((s.indexOf(entry.getKey()) + entry.getKey().length() < s.length()) && ((s.charAt(s.indexOf(entry.getKey()) + entry.getKey().length()) != ' ')))) {
                                //对双引号
                                if (s.indexOf('"') >= 0 && (s.indexOf('"') < s.indexOf(entry.getKey())) && ((s.substring(s.indexOf('"') + 1)).indexOf('"') > 0) && ((s.substring(s.indexOf('"') + 1)).indexOf('"') > s.indexOf(entry.getKey()))) {
                                    s = s.substring(s.indexOf('"') + 2 + ((s.substring(s.indexOf('"') + 1)).indexOf('"')));
                                    if (s.contains(entry.getKey())) entry.setValue(entry.getValue() + 1);
                                }

                            } else {
                                entry.setValue(entry.getValue() + 1);
                            }
                            if (s.contains(entry.getKey()) && is == 1) {
                                s = s.substring(s.indexOf(entry.getKey()) + entry.getKey().length());
                            }
                        }
                    }
                }
            }
        }
    }

    public static List makeMap(String str) throws IOException {

        Map<String, Integer> map = new HashMap<>();

        for (String keyword : KEYWORDS) {//初始化关键词map
            map.put(keyword, 0);
        }

        if (str.contains(".java")) {
            check(map, str);
        } else {
            File fdir0 = new File(str);
            for (int i = 0; i < Objects.requireNonNull(fdir0.list()).length; i++) {//遍历每个文件
                if (Objects.requireNonNull(fdir0.list())[i].contains(".java")) {
                    String strAddress = str + "/" + Objects.requireNonNull(fdir0.list())[i];
                    check(map, strAddress);
                }
            }
        }

        //自定义比较器
        Comparator<Map.Entry<String, Integer>> valCmp = (o1, o2) -> {
            // TODO Auto-generated method stub
            return o2.getValue() - o1.getValue();  // 降序排序,如果想升序就反过来
        };
        //将map转成List,map的一组key,value对应list一个存储空间
        List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet()); //传入maps实体
        list.sort(valCmp); //对list进行排序

        return list;
    }

}


第六个类(接口):CorrectRoad

作用:只是一个寻找/的函数,主要很多个地方都要用到,一个个都写的话,代码量多。

代码:

package finalExam;

public interface CorrectRoad {

    static int nameWhere(String str) {//找出str中最后一个"/"的位置
        int i;
        for (i = str.length() - 1; i >= 0; i--) {
            if (str.charAt(i) == '/') break;
        }
        return i;
    }

}

类图:

在这里插入图片描述

总结:

每次这种课程设计不要太马虎去对待,!态度决定一切!。

一看到这种题,不要慌,现从主函数下手,构建好一个主体后,就先后实现每个小功能,然后在对自己完成的程序进行优化,这样的顺序下来做课程设计事半功倍。

然后不懂的那些,多想几天,多试几天,很容易开窍的,实在不会,实在试了很多天,还是不会,那就参考其它大佬的代码,读懂它们。

最后发现问题的请指出!

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值