[Python编程]综合性实验: Java源代码分析程序 (统计文件,行数,关键字)

又重新对做过的课设用新的语言实现了一次,学到了很多知识…
这是上一次实现的[Java]综合性实验 Java源代码分析程序
分为三个部分
1.统计指定目录中文件的个数和总的大小
2.统计目录下Java源文件的关键字出现次数
3.统计Java源文件代码行数,注释行数,空白行数

实验要求如下:

一、题目:综合性实验 Java源代码分析程序
二、类型:综合型、探索型
三、目的:初步掌握运用面向对象方法编写应用程序,掌握类、对象、封装等;了解并应用Java语言的字符串处理、文本文件的读写
四、内容:
1.背景描述:
(1)Java语言共有50个关键字。
(2)Java源程序是以“.java”为扩展名的文本文件。
(3)可以考虑在Java源程序中的行共有3种:
代码行,可运行的Java源代码。例如:
int n = 10;
注释行,3种注释均可。例如:
/**
文档注释
/
/

多行注释
/
//单行注释
空行,既无代码,也无注释;
(4)特殊行的处理方法
如果有以下行尾单行注释的情况,将该行判定为代码行。
int number; //number表示人数
int n; /n表示数量/
如果有以下行尾多行注释的情况,第1行判定为代码行,第二行判定为注释行。
int number; /
number为整型
表示人数 */
假设被分析程序源码无其他特殊情况,如:
int /人数/ number;
2. 项目名和类名为JavaCodeAnalyzer,主类名等其他类名自行定义。
3. 实现功能:
(1) 程序运行时要求输入一个目录的名称。目录不存在或不是目录要提示错误并重新输入。
(2) 找出输入目录中所有的Java源程序文件(文件扩展名为“.java”), 并进行源程序文件进行分析。
需要分析的结果有:
目录中源程序文件个数
所有源程序文件总的字节数
所有源程序文件中代码行数、注释行数、空行数及总行数。说明:行以回车结束。
(3) 统计并按从多到少输出所有源程序文件中使用的Java关键字及其出现次数。
(4) 统计分析的结果除在屏幕显示外,还需要存储到一个文本文件中,文件内容应该如下:
目录名称:XXXXX(绝对路径方式)
共有源程序文件XX个,总的大小为:XXXXXX 字节
源程序文件总行数:xxxx,其中:
代码行数:xxx,占xx.xx%
注释行数:xxx,占xx.xx%
空白行数:xxx,占xx.xx%
源程序文件中使用过的关键字有(按使用次数降序排列):
关键字1:xx次
关键字2:xx次
关键字3:xx次
关键字4:xx次
关键字5:xx次
本次分析时间:年-月-日,时-分-秒
注意:统计关键字使用次数时,要排除注释中出现的关键字和字符串直接量中出现的关键字。

分成以下部分:
1.验证输入目录
2.递归搜索.java格式文件
3.计算.java文件个数和总大小
4.统计源文件的代码行数,注释行数等
5.统计源文件的关键字出现次数
6.将输出结果保存到文件(偷懒不实现,用file模块)
7.输出计算用时(偷懒不实现,用timeit模块)

代码实现

class JavaCodeAnalyzer:
    def __init__(self):
        self.filelist = []
        self.filepath = ""
        self.row_count = self.blank_count = self.note_count = self.code_count = 0
        self.keywords = {key: 0 for key in
                         ["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", "strictfp", "short", "static", "super",
                          "switch", "synchronized", "this", "throw", "throws",
                          "transient", "try", "void", "volatile", "while"]}

    def getpath(self):
        '验证输入目录'
        while True:
            try:
                self.filepath = input("输入目录路径: ")
                listdir(self.filepath)
            except:
                print("输入不是目录或目录有误,请重新输入")
            else:
                break

    def search(self, path):
        '递归搜索.java格式文件'
        files = listdir(path)
        for file in files:
            self.filepath = path + "\\" + file
            if op.isdir(self.filepath):
                self.search(self.filepath)
            else:
                if self.filepath.endswith('.java'):
                    self.filelist.append(self.filepath)

    def count(self):
        '计算.java文件个数和总大小'
        length = len(self.filelist)
        size = sum([op.getsize(file) for file in self.filelist])
        print("文件总数:", length)
        print("文件总大小:", size)

    def keyword_analyze(self, filepath):
        '统计源文件的关键字出现次数'
        with open(filepath) as file:
            lines = file.read().split('\n')  # 一次性读取一个文件,并用换行分割每一行
        for line in lines:
            noteline = re.match(r'^/(.*)|^\*(.*)|(.*)\*/$', line.strip(), flags=0)  # 匹配以/* 或者* 或者 //开头 或*/结尾的注释行
            if noteline is None:  # 匹配为代码行
                codeline = re.sub(r'//(.*)$|/\*(.*)|\"(.*)\"', '', line)  # 去除行后注释,字符串直接量的代码行
                filterline = re.sub('\W', ' ', codeline)  # 过滤行中'{ , } .+-='等字符
                for key in filterline.split(' '):
                    if key in self.keywords.keys():
                        self.keywords[key] = self.keywords[key] + 1
            else:
                pass

    def code_analyze(self, filepath):
        '统计源文件的代码行数,注释行数等'
        with open(filepath) as file:
            lines = file.read().strip().split('\n')  # 一次性读取一个文件,并用换行分割每一行
            self.row_count += len(lines)
        for line in lines:
            if line == '':
                self.blank_count += 1
                continue
            noteline = re.match(r'^/(.*)|^\*(.*)|(.*)\*/$', line.strip(), flags=0)  # 匹配以/、/* 、*开头 或*/结尾的注释行
            if noteline is None:  # 匹配为代码行
                self.code_count += 1
            else:
                self.note_count += 1

    def display(self):
        '输出分析结果'
        print("源程序总行数:", self.row_count)
        print("代码行数:", self.code_count, ",占", round(self.code_count / self.row_count * 100, 2), "%")
        print("注释行数:", self.note_count, ",占", round(self.note_count / self.row_count * 100, 2), "%")
        print("空白行数:", self.blank_count, ",占", round(self.blank_count / self.row_count * 100, 2), "%")
        for i in range(5):
            sort = sorted(self.keywords.items(), key=lambda x: x[1], reverse=True)
            print("关键字  ", sort[i][0], ": ", sort[i][1], "次")

测试

if __name__ == '__main__':
    jca = JavaCodeAnalyzer()
    jca.getpath()
    jca.search(jca.filepath)
    jca.count()
    for f in jca.filelist:
        jca.code_analyze(f)
        jca.keyword_analyze(f)
    jca.display()

分析util文件夹得到结果如下:
java.util-百度网盘

在这里插入图片描述

说在后面

这次实现比上次用java重构的要快,而且质量要高,几乎通过了所有的用例。而且代码简短,在java中我写了200行左右,而python只用了100行(而且含分隔的空行!) 可见Python真的很好用…

猜你喜欢

转载自blog.csdn.net/xHibiki/article/details/83792265