个人项目

news/2024/11/15 16:22:37/文章来源:https://www.cnblogs.com/lzy394/p/18408092
这个作业属于哪个课程 计科22级12班
这个作业要求在哪里
作业要求
这个作业的目标 完成个人项目,实现论文查重的功能,了解软件开发流程

Github链接

一.PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 15 20
Estimate 估计这个任务需要多少时间 60 70
Development 开发 180 200
Analysis 需求分析 (包括学习新技术) 30 45
Design Spec 生成设计文档 60 70
Design Review 设计复审 30 30
Coding Standard 代码规范 (为目前的开发制定合适的规范) 15 15
Design 具体设计 25 20
Coding 具体编码 90 110
Code Review 代码复审 60 40
Test 测试(自我测试,修改代码,提交修改) 30 50
Reporting 报告 120 110
Test Repor 测试报告 30 25
Size Measurement 计算工作量 15 15
Postmortem & Process Improvement Plan 事后总结,并提出过程改进计划 40 40
合计 800 860

二.项目设计

功能实现

为了比较两个文本的相似程度,这里先使用HanLp的分词工具将文本划分成多个关键词,之后用SimHash算法将这些关键词向量化再经过加权合并,合并的结果进行降维处理后获得文本的Simhash值,之后求出两个文本Simhash的海明距离,即两个字符串相同位置不同字符的个数,最后得出两个文本的重复率。

项目流程

文件结构

类图

实现关键

该算法的重点在于对文本文件内容的分词处理和相似度的计算,一开始我使用的是Ansj分词工具,可以运行出结果,但是会包含一部分的运行信息(如下图)。

所以后面改用了HanLp实现分词功能,相关配置参考了博客,而在得到文章的分词结果之后问题就变为如何计算这些词语的相似度,这里我用的是SimHash算法加海明距离来计算两个文本内容的重复率。由于SimHash算法中会对所有分词进行加权处理,所以即使将语句次序变换或者将文章打乱,使用SimHash算法所得出的结果也不会有太大变化。

三.性能分析

性能分析部分使用了JProfiler工具。

内存分配情况:

由于需要用列表记录分词结果,还要设置向量进行计算处理,消耗的内存还是比较大的。
目前打算的改进方向是看看能不能在分词的同时计算特征向量,可以减少空间开销,以及在这个基础用字词库(像Ansj在运行时用字词库可以提供更准确的分词结果),加快分词速度并提高查重结果的准确度。

四.单元测试

单元测试时我用的是Junit,但其实在IDEA里面新建Maven项目时会自动创建一个test文件夹用于编写测试类。

点击查看代码
@Testpublic void a_testParameterNum() {//参数个数测试assertEquals("提供的参数个数不正确",assertThrows(Exception.class, ()-> Main.main(new String[]{""})).getMessage());}@Testpublic void b_testNullPath()  {//查重文件路径为空测试assertEquals("参数中的文件路径为空",assertThrows(Exception.class, ()-> Main.main(new String[]{null, "", ""})).getMessage());}@Testpublic void c_testNull_ansPath() {//答案文件路径为空测试assertEquals("答案文件路径为空,无法将结果写入",assertThrows(Exception.class, ()-> Main.main(new String[]{"D:\\Javacode\\PersonalProject\\orig.txt","D:\\Javacode\\PersonalProject\\orig_0.8_add.txt",null})).getMessage());}@Testpublic void d_testNotExist_ansFile()  {//答案文件不存在测试assertEquals("答案文件不存在",assertThrows(Exception.class, ()-> Main.main(new String[]{"D:\\Javacode\\PersonalProject\\orig.txt","D:\\Javacode\\PersonalProject\\orig_0.8_add.txt","D:\\Javacode\\PersonalProject\\a.txt"})).getMessage());}@Testpublic void e_testNotExist_File(){//查重文件不存在测试assertEquals("文件testfile1.txt不存在,无法查重",assertThrows(Exception.class, ()-> Main.main(new String[]{"D:\\Javacode\\PersonalProject\\testfile1.txt","D:\\Javacode\\PersonalProject\\orig_0.8_add.txt","D:\\Javacode\\PersonalProject\\ans.txt"})).getMessage());}@Testpublic void f_testEmpty_File(){//查重文件为空测试assertEquals("文件testfile2.txt内容为空",assertThrows(Exception.class, ()-> Main.main(new String[]{"D:\\Javacode\\PersonalProject\\testfile2.txt","D:\\Javacode\\PersonalProject\\orig_0.8_add.txt","D:\\Javacode\\PersonalProject\\ans.txt"})).getMessage());}@Testpublic void g_testShort_File(){//查重文件过短测试assertEquals("文件testfile3.txt内容过短",assertThrows(Exception.class, ()-> Main.main(new String[]{"D:\\Javacode\\PersonalProject\\testfile3.txt","D:\\Javacode\\PersonalProject\\orig_0.8_add.txt","D:\\Javacode\\PersonalProject\\ans.txt"})).getMessage());}@Testpublic void h_test1() throws Exception {Main.main(new String[]{"D:\\Javacode\\PersonalProject\\orig.txt","D:\\Javacode\\PersonalProject\\orig_0.8_add.txt","D:\\Javacode\\PersonalProject\\ans.txt"});}@Testpublic void i_test2() throws Exception {Main.main(new String[]{"D:\\Javacode\\PersonalProject\\orig.txt","D:\\Javacode\\PersonalProject\\orig_0.8_del.txt","D:\\Javacode\\PersonalProject\\ans.txt"});}@Testpublic void j_test3() throws Exception {Main.main(new String[]{"D:\\Javacode\\PersonalProject\\orig.txt","D:\\Javacode\\PersonalProject\\orig_0.8_dis_1.txt","D:\\Javacode\\PersonalProject\\ans.txt"});}@Testpublic void k_test4() throws Exception {Main.main(new String[]{"D:\\Javacode\\PersonalProject\\orig.txt","D:\\Javacode\\PersonalProject\\orig_0.8_dis_10.txt","D:\\Javacode\\PersonalProject\\ans.txt"});}@Testpublic void l_test5() throws Exception {Main.main(new String[]{"D:\\Javacode\\PersonalProject\\orig.txt","D:\\Javacode\\PersonalProject\\orig_0.8_dis_15.txt","D:\\Javacode\\PersonalProject\\ans.txt"});}

前面的测试主要是用Assert断言验证异常是否正确抛出(异常处理在下一个部分,包括空文件,文件不存在或文件过短等情况),后面5个是原文和各个抄袭文本的结果输出。
这里是各个测试命名开头是因为Jvm返回的结果有随机性,用了语句@FixMethodOrder(MethodSorters.NAME_ASCENDING)后会按方法名的字典序返回测试结果,为了让结果规范点就用abcdef开头了。

测试结果如下:

时间花费主要在HanLp的extractKeyword方法上,基本上不到4s可以跑完5个抄袭文件的查重结果。

测试覆盖率如下:

四.异常处理

在设计模块时只考虑了实现功能,没有将异常情况都划分到一个类里面,有点零零散散,不过这些异常基本上都是在读写文件时抛出。

main参数异常

点击查看代码
if(args.length !=3){System.out.println("提供的参数个数不正确");throw new Exception("提供的参数个数不正确");}

原文或抄袭文件路径为空

点击查看代码
if(Path1==null||Path1.isEmpty()||Path2==null||Path2.isEmpty())//判断文件路径是否为空{System.out.println(NullPathErrorMessage);throw new Exception(NullPathErrorMessage);}

答案文件的路径为空

点击查看代码
if(Path3==null||Path3.isEmpty()) {//路径为空System.out.println(nullPathErrorMessage);throw new Exception(nullPathErrorMessage);}

路径为有效字符串,但原文或抄袭文件不存在

点击查看代码
if(!file.exists()) {//判断文件是否存在System.out.println(FileNotExistsErrorMessage);throw new Exception(FileNotExistsErrorMessage);}

路径为有效字符串,但答案文件不存在

点击查看代码
if(!new File(Path3).exists()){throw new Exception("答案文件不存在");}

原文或抄袭文件内容为空

点击查看代码
if(str.toString().isEmpty()) {//判断文件内容是否为空String EmptyFileErrorMessage="文件"+filename+"内容为空";System.out.println(EmptyFileErrorMessage);throw new Exception(EmptyFileErrorMessage);}

原文或抄袭文件内容过短

点击查看代码
if(str.toString().isEmpty()) {//判断文件内容是否为空String EmptyFileErrorMessage="文件"+filename+"内容为空";System.out.println(EmptyFileErrorMessage);throw new Exception(EmptyFileErrorMessage);}

异常的各个测试用例结果:

后续修改代码的话应该会把这些异常写在用一个专门的Exception类,方便分模块处理。

五.运行结果

这个是打包后的jar包运行,我放在了main的resources文件夹下,由于我用的环境是jdk21,在其他jdk环境的机器上运行可能会提示版本不适配的问题。

可以正常运行出结果并且写入指定的文件中(前五个是单元测试的结果)

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

互联网医疗|基于音视频SDK和即时通讯IM技术实现线上问诊功能

不论是科普医学知识,还是医疗行业者的专业培训、手术示教,采用远程直播培训的方式能够打破空间限制,同时也保留了课堂的互动性,大大节省了讲师和学员的成本。帮助开发者全面监测音视频服务,包括问题定位诊断、洞察质量与体验、业务经营分析、实时监控告警等,低门槛、高效…

Spring boot 2.x validator

1、使用方式 2、常用注解

DBeaver 连接 mysql 报错:Public Key Retrieval is not allowed

前言 DBeaver 连接 mysql 报错:Public Key Retrieval is not allowed 遇到 "Public Key Retrieval is not allowed" 错误时,通常意味着你正在使用的身份验证方法需要加密连接,但是没有正确地配置客户端或服务器来支持这种加密。 解决 第一种 可以在连接字符串中添…

Rest-assured框架详解

Rest-assured框架官网 官网url: https://rest-assured.io/ 一、接口测试介绍 - 什么是接口测试 本质上基于某种协议,发送请求给服务器,服务器返回响应数据,对响应数据进行分析,判断和我们的预期是否一致,从而验证功能是否正确。 - 为什么做接口测试 更早发现问题,降低研…

Google Play中无法更新Chrome和Android System Webiew的解决办法

【1】去https://apkpure.com/下载安装最新的Apkpure;【2】打开Apkpure,搜索Google Play,然后更新到最新版本;【3】重新打开Google Play,点自己头像,打开管理应用和设备,你会发现已经不需要更新Android System Webiew了,并且此时可以搜索任何APP进行安装,包括之前极难更…

Consul Windows部署

一、Consul下载 下载地址:Install | Consul | HashiCorp Developer 本次使用Windows版本下载解压后,可看到consul.exe文件二、Consul Server配置 为了方便使用增加server-config.hcl和server-start.bat文件(一) server-config.hcl配置文件 # 节点名称 node_name = "my-c…

国产化:部署单机THS(东方通TongHttpServer替代Nginx)

背景 国产化要求,使用东方通 TongHttpServer 替代 Nginx 。1 安装THS 解压之后把授权文件 license.dat 放到主目录下即可。 tar zxvf TongHttpServer_6.0.0.2_x86_64.tar.gz2 启动主程序 如果以 root 用户启动 THS 时,worker 进程会切换到 nobody 用户 nobody 组运行。所以确…

magma软件许可优化解决方案

Magma软件介绍 MAGMA在90年代初通过代理进入中国市场。为了更好快速的服务中国的客户、带来更便捷的、中文语言的技术支持和培训,2009年,MAGMA德国在中国正式设立分公司,即迈格码(苏州)软件科技有限公司(以下简称为MAGMA中国),从事MAGMA的销售和售后活动,服务中国大陆…

又发现2个bug

bug1 设置缓存过期未注意单位,导致一下失效了bug2 由于bug1 缓存失效导致 bug2 gorm,结构体里面有重复的字段,查询未报错,直接赋值成为了默认值 导致了程序异常 顺便编写了一个脚本,擦了一下屁股,之前的bug 修复了,数据未完全处理,导致偶尔有人反馈异常

关于RTX 4090 微调llama2模型时出现nvcc fatal : Unsupported gpu architecture compute_89的解决办法

RTX 4090是现在普通人可以轻松获取的最好的显卡了。运算速度仅次于专业图形卡Tesla A100,A800,H100 RTX4090显卡是可以单卡推理llama2 7b和13b模型的,7b模型占用缓存14G左右,13b模型单卡推理显存占用在23G多点(只是运行一段时间容易爆显存),所以普通人都是可以使用llama2大…

从注册到实战,超简单图床使用(附代码实现本地图片转换为网络url)

1.注册一个薄荷图床的的账号,并添加客服申请api测试权限 ​ 查看api文档 我们只需关注两个必选参数即可,如图中红色标注 2.编写pthon代码 ​ 其他语言也可以,只要发送post请求即可,注意url、token和照片需要更改为你自己的 import requestsdef python_demo():url = https:…