代码相似性检测工具

背景

最近由于工作需要,想找一个能够检查代码相似性的工具。这种工具主要有两个应用:

  • 代码自身的冗余检查

  • 查重,例如检查学生的编程作业是否有抄袭

工具

最后找到了两个工具simmoss,具体实现算法还没有研究,但是moss需要申请,并且通过网络使用,这样速度、灵活性和安全性都是有缺陷的,所以选择了sim

这个工具编译起来也很麻烦,而且没有mac的版本,幸好已经有人编了一个https://github.com/fanghon/antiplag/blob/master/sim_java.exe[Windows版本可执行文件],先用着。

扩展

由于我是要比较两个项目,并且按照相似性排序,但是sim本身的参数似乎不支持,所以写了一个脚本(moss后端不在本地,这种定制能力就做不了)

import os

dir1 = "*******"
dir2 = "*******"

target_file_list_1 = []
target_file_list_2 = []


def gen_file_list(dir_name, suffix_name):
    temp = []
    for root, dirs, files in os.walk(dir_name):
        for file in files:
            if file.endswith(suffix_name):
                temp.append(os.path.join(root, file))
    return temp


target_file_list_1 = gen_file_list(dir1, ".java")
target_file_list_2 = gen_file_list(dir2, ".java")

result = []

def parse_result(text):
    for line in text.split("\n"):
        if " % of " in line:
            line_arr = line.split(" ")
            result.append([line_arr[0], line_arr[-2], line_arr[3]])
            break


total = len(target_file_list_1) * len(target_file_list_2)

cnt = 0
for from_f in target_file_list_1:
    for to_f in target_file_list_2:
        cnt += 1
        ret = os.popen("sim_java.exe -p {} {}".format(from_f, to_f))
        parse_result(ret.read())
        print("{} / {}".format(cnt, total))

result.sort(key=lambda d: int(d[2]), reverse=True)
with open("./out.txt", 'w') as f:
    for item in result:
        f.write(str(item) + "\n")