第一次个人编程作业———论文查重
这个作业属于哪个课程 | 广工2023软件工程课程 |
---|---|
这个作业要求在哪里 | 个人项目作业-论文查重 |
这个作业的目标 | 1.学习对工程进行单元测试 2.学习PSP表格的制作 3.学习对工程文件进行性能分析和内存分析 |
其他参考文献 | CSDN |
文章目录
一、项目地址
二、PSP表格
PSP2.1 | Personal Sortware Process Stages | 预计耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 45 |
·Esitmate | ·估计这个任务需要多少时间 | 1920 | 1955 |
Development | 开发 | 800 | 900 |
·Analysis | ·需求分析(包括学习新技术) | 200 | 210 |
·Design Spec | ·生产设计文档 | 30 | 25 |
·Design Review | ·设计复审 | 30 | 40 |
·Coding Standard | ·代码规范(为目前的开发指定合适的规范) | 10 | 5 |
·Design | ·具体设计 | 90 | 90 |
·Coding | ·具体编码 | 300 | 240 |
·Code Review | ·代码复审 | 60 | 40 |
·Test | ·测试(自我测试、修改代码、提交修改) | 180 | 150 |
Reporting | 报告 | 90 | 120 |
·Test Repor | ·测试报告 | 60 | 45 |
·Size Measurement | ·计算工作量 | 20 | 20 |
·Postmortem & Process Improvement Plan | ·事后总结,并提出过程改进计划 | 20 | 25 |
·合计 | 1920 | 1955 |
三、计算模块接口的设计和实现过程
3.1 系统流程
3.2 所用的类
3.2.1 文件读写类
FileUtil类,有readFile()和writeFile()两个方法。引入了糊涂工具包里面的FileReader,对异常进行了封装,设计了读、写文件两个方法。
3.2.2 自定义异常类
fileException类。用于处理FileUtil类的异常。
3.2.3 分词计算类
TokenizerUtil类。包括CountWord()和CosCount()方法,分别用于分词和文本相似度计算。
3.3 算法关键
3.3.1 分词
分词的方法引用了糊涂工具包的TokenizerEngine,并且通过hankc当作引擎作分词处理,这里我用到的是hanlp分词,遍历存放着词和词频的结果树,通过结果树存储计算cos值。
3.3.2 文本相似度的计算
1)思路
使用向量余弦计算文本相似度。思路如下:
- 通过中文分词(此处使用HanLP工具),把完整的句子根据分词算法分为独立的词集合,为降噪,将标点符号过滤掉
- 求出两个词集合的并集,得到输入文本中的所有词;
- 计算各自词集的词频并作为特征值;
- 带入向量计算模型就可以求出文本相似度。
查阅许多资料对比发现,该方法优势在于代码实现难度较低,向量计算模型拟合情况良好,但对于处理长文本的话,该方法速度较慢,但也能基本覆盖需求。
2)向量余弦计算模型
- 余弦相似性的定义:两个向量的家教越接近于0,其余弦值越接近1,表面两个向量越相似。
- 计算模型:
四、计算模块接口部分的性能改进
4.1 JProfiler分析
- 概览图
花费时间约为2s - 性能分析图
4.2 消耗最大的函数
用于计算向量余弦值的CosCount函数。
4.3 性能改进思路
由性能分析图可见,Linklist占据了较多的性能,原因是Linklist查询性能较差,遍历较慢,可以尝试将linkList替换为ArrayList。
五、计算模块部分单元测试展示
- 单元测试代码
测试函数说明已注释
/**
* 封装测试方法。
*
* @param firstPath 第一个测试文件的路径
* @param secondPath 第二个测试文件的路径
*/
public void test(String firstPath, String secondPath, String testDetail) {
Map<String, List<Integer>> firstListMap = TokenizerUtil.CountWord(firstPath);
Map<String, List<Integer>> secondListMap = TokenizerUtil.CountWord(secondPath);
Double similarity = TokenizerUtil.CosCount(firstListMap, secondListMap);
String result = testDetail + similarity;
FileUtil.writeFile("D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\result.txt", result);
System.out.println(result);
}
/**
* 空白文件测试样例
*/
@Test
public void testNullFilePath() {
test("", "", "空白文件测试结果为:");
}
/**
* 相同性测试样例
*/
@Test
public void testSame() {
test("D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig.txt", "D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig.txt", "相同性测试结果为:");
}
/**
* 增加文本与原文本测试样例
*/
@Test
public void testAdd() {
test("D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig.txt", "D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig_0.8_add.txt", "原先文本和增加文本的对比测试结果为:");
}
/**
* 删除后的文本与原文本测试样例
*/
@Test
public void testDelete() {
test("D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig.txt", "D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig_0.8_del.txt", "原先文本与删除部分文字的文本对比测试结果为:");
}
/**
* 原文本与dis1文本测试样例
*/
@Test
public void testDis1() {
test("D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig.txt", "D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig_0.8_dis_1.txt", "原文本与dis1文本测试结果为:");
}
/**
* 原文本与dis10文本测试样例
*/
@Test
public void testDis10() {
test("D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig.txt", "D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig_0.8_dis_10.txt", "原文本与dis10文本测试结果为:");
}
/**
* 原文本与dis15文本测试样例
*/
@Test
public void testDis15() {
test("D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig.txt", "D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig_0.8_dis_15.txt", "原文本与dis15文本测试结果为:");
}
/**
* dis1与dis10测试样例
*/
@Test
public void testCommon1() {
test("D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig_0.8_dis_1.txt", "D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig_0.8_dis_10.txt", "dis1与dis10文件测试结果为:");
}
/**
* dis1与dis15测试样例
*/
@Test
public void testCommon2() {
test("D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig_0.8_dis_1.txt", "D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig_0.8_dis_15.txt", "dis1与dis15文件测试结果为:");
}
/**
* dis10与dis15测试样例
*/
@Test
public void testCommon3() {
test("D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig_0.8_dis_10.txt", "D:\\Java_demo\\软件工程作业\\3121005168论文查重作业\\text_example\\orig_0.8_dis_15.txt", "dis10与dis15文件测试结果为:");
}
- 思路
- 五个抄袭的文件与原文件构成五个测试样例
- 五个抄袭文件构成三个测试样例
- 两个空白文件构成一个测试样例
- 两个相同文件构成一个测试样例
-
样例结果
-
代码覆盖率
六、计算模块部分异常处理说明
- 文件异常处理
如果输入的文本的路径为空,会提示“文件路径为空”,不会导致程序异常退出。同时若所读的文件中没有内容,会提示“文件为空”。