统计Java源代码中关键字的数目(每个关键字的数目)

题目要求:编写一个程序,读取一个java源代码文件(.java),然后报告该文件中关键字的个数。从命令行传递这个java源文件。

以下代码从IDEA中的程序运行参数中传入 任意文件或目录的绝对路径,此步骤等价于“从命令行传递任意文件或目录”的绝对路径。

若是目录则获取目录下的所有子文件或子目录的绝对路径递归调用该方法,对.java文件和子目录中.java进行统计;
若是.java文件则直接统计。

统计Java源代码中关键字的数目(每个关键字的数目)_第1张图片

统计Java源代码中关键字的数目(每个关键字的数目)_第2张图片

此外以下程序使用了与java源代码在相同文件夹下存储Java所有关键字的文本文件(.txt)。

统计Java源代码中关键字的数目(每个关键字的数目)_第3张图片

代码使用HashMap存储所有关键字及其个数,检索效率较高。

可以检索格式化(规范)的代码(这里指类似于IDEA中经过 Ctrl+Alt+L 格式化的代码)

分析:经过格式化(规范)的代码后,大部分Java关键字都在代码中处于 "    关键字    "(关键字两边都是空格)的情况。

但有些较特殊的情况,需要我们特殊处理,例如:

while (true) {// (true)  true关键字

     if (条件) {
        break;
     }

}
continue;
super.方法名(参数);
this.方法名(参数);

这几种情况,格式化(规范)代码后,关键字不是“独立”的存在而是与其他字符“连”在一起。

另外类似:

System.out.println("private public protected..."); //字符串中存在关键字

不应该被统计在内。 

代码:

package count;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;

public class CountKeywords {
    private static HashMap records = new HashMap<>();//用于存储关键字

    /**
     * 获取关键字
     */
    private static void getKeywords() {
        /*
         *在程序中,不要直接使用绝对文件名。如果使用了像 c:\\book\\Welcome.java 之类的文
         *件名,那么它能在 Windows上工作,但是不能在其他平台上工作。应该使用与当前目录相
         * 关的文件名。例如,可以使用 new File("welcome.java")为在当前目录下的文件 Welcome.java
         *  创建一个 File 对象。可以使用 new File("image/us.gif")为在当前目录下的 image目
         * 录下的文件 us.gif创建一个 File 对象。斜杠(/)是 Java 的目录分隔符,这点和 UNIX 是一样的。
         * 语句 new File(image/us.gif")在 Windows、UNIX 或任何其他系统上都能工作。
         */
        File file = new File("src/count/keywords.txt");//通过存储关键字的文本文件获取关键字并存储
        if (!file.exists()) {
            System.err.println("Keywords-file does not exist!");
            System.exit(0);
        }
        try (Scanner scanner = new Scanner(file)) {
            while (scanner.hasNext()) {
                records.put(scanner.next(), 0);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    static {
        getKeywords();
    }

    public static void main(String[] args) {
        File file = new File(args[0]);
        if (!file.exists()) {//对输入的“命令行”路径参数进行检验
            System.err.println("File or directory does not exist!");
            System.exit(0);
        } else {
            checkAndCountFromFile(args[0]);
        }
        Set keywordsSet = records.keySet();
        for (String keyword : keywordsSet) {//遍历统计的各个关键字的结果
            System.out.println(keyword + " : " + records.get(keyword));
        }
    }

    /**
     * 统计.java文件中各个关键字的个数
     * 若是目录则获取目录下的所有子文件或子目录的绝对路径递归调用该方法,对.java文件和子目录中.java进行统计
     * 若是.java文件则直接统计
     *
     * @param path 文件或目录的绝对路径
     */
    private static void checkAndCountFromFile(String path) {
        File[] files;
        File file = new File(path);
        if (file.isDirectory()) {//若是目录则获取目录下的所有子文件或子目录的绝对路径递归调用该方法,对.java文件和子目录中.java进行统计
            files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                checkAndCountFromFile(files[i].getAbsolutePath());
            }
        } else if (file.isFile()) {//若是.java文件则直接统计
            if (file.getName().endsWith(".java")) {
                try (Scanner scanner = new Scanner(file)) {
                    while (scanner.hasNext()) {
                        checkAndCountFromStr(scanner.next());
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 检查从Java源文件中逐个读取的字符串并且对关键字逐个统计数目
     *
     * @param string 从Java源文件中逐个读取的字符串
     */
    private static void checkAndCountFromStr(String string) {
        if (records.containsKey(string)) records.put(string, records.get(string) + 1);
        switch (string) {
            case "(true)":
                records.put("true", records.get("true") + 1);
                break;
            case "break;":
                records.put("break", records.get("break") + 1);
                break;
            case "continue;":
                records.put("continue", records.get("continue") + 1);
                break;
        }
        if (string.length() > 6) {
            if (string.substring(0, 6).equals("super.")) records.put("super", records.get("super") + 1);
            if (string.substring(0, 5).equals("this.")) records.put("this", records.get("super") + 1);
        }
    }
}

执行结果:

      统计Java源代码中关键字的数目(每个关键字的数目)_第4张图片   统计Java源代码中关键字的数目(每个关键字的数目)_第5张图片

统计Java源代码中关键字的数目(每个关键字的数目)_第6张图片

该程序在处理以下情况时不能准确统计Java源文件中各个关键字的个数:

//  关键字   关键字  关键字 ...

单行注释中存在“间断”的关键字情况。

/**
*  关键字  关键字
*  关键字  关键字  关键字
*/

多行注释或文档注释中存在“间断”的关键字情况。

String str = "关键字  关键字";
System.out.println(" 关键字   关键字");

字符串中存在“间断”的关键字情况。

如果想要处理以上三种情况,可以使用正则表达式结合字符串的相关处理方法进行解决。

若有错误还请斧正。

你可能感兴趣的:(Java,数据结构与算法,java)