第一次个人编程作业
|  这个作业属于哪个课程    |  软件工程 |
| ---- | :----: | :----: |
| 这个作业要求在哪里 |  作业要求  |
| 这个作业的目标 | 论文查重算法设计+单元测试+JProfiler+PSP表格+Git |
代码链接
计算模块接口的设计与实现过程
整体流程
1.PaperCheckMain.main方法接收三个参数,分别为 [原文文件] [抄袭版论文的文件] [答案文件]
2.将两个文件的文本内容分别转换为字符串
3.CosSimilarityServiceImpl.getSimilarity,使用余弦相似算法对比字符串
4.将结果输出到指定文件
工程结构

项目主要类
- PaperCheckMain:程序的入口
- CosSimilarityServiceImpl:余弦算法的实现计算相似度
- FileUtil:处理文件、将文件内容转化为字符串、将结果输出到指定文件中
- IKSegmenter: 分词器
命令行运行效果

算法描述
文本相似度算法:余弦相似度算法
- 1.分词
- 2.列出所有词
- 3.计算词频向量
- 4.利用HashMap存储词和对应的词频,词为健,词频为值
- 5.使用余弦公式计算cos值
- 6.cos值越接近1,两篇文章相似度越高
- 7.参考文章
- 8.余弦公式
 ![]() 
计算模块接口部分的性能改进
使用JProfiler进行单元测试对性能进行监控
- 
类的内存消耗 
 ![]() 
- 
CPU Load 
 ![]() 
- 
堆内存情况 
 ![]() 
- 
改进思路 
 1.最耗时的地方是对字符串进行分词操作,但对IK分词器难以优化,所以无法对分词进行操作,或许可能更换更加优秀的分词器
 2.可对字符串的判断进行优化,比如利用String.equals进行对比或判断字符串文本内容是否为空简略优化
计算模块的单元测试展示
单元测试使用Junit
- 测试路径为null的情况、测试空文本、相同文本、不同文本、干扰文本、参数输入错误等情况
- PaperCheckMain.process使用静态方法,输入参数为 [原文文件] [抄袭版论文的文件] [答案文件]
    /**
     * 测试原创论文路径为null的情况
     */
    @Test
    public void testForOriginalContextNull(){
        try {
            PaperCheckMain.process(null,"E:\\test\\orig_0.8_add.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            System.out.println("输入参数不能为空!");
        }
    }
    /**
     * 测试抄袭论文路径为null的情况
     */
    @Test
    public void testForCopyContextNull(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt",null,"E:\\test\\result.txt");
        } catch (MyException e) {
            System.out.println("输入参数不能为空!");
        }
    }
    /**
     * 测试输出结果文件路径为null的情况
     */
    @Test
    public void testForResultFileAddressNull(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_add.txt",null);
        } catch (MyException e) {
            System.out.println("输入参数不能为空!");
        }
    }
    /**
     * 测试输出抄袭论文为空文本的情况
     */
    @Test
    public void testForCopyContextEmptyNull(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\empty.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
    /**
     * 测试对比orig.txt与orig_0.8_add.txt
     */
    @Test
    public void testForCopyContextAdd(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_add.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
    /**
     * 测试对比orig.txt与orig_0.8_del.txt
     */
    @Test
    public void testForCopyContextDel(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_del.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
    /**
     * 测试对比orig.txt与orig_0.8_dis_1.txt
     */
    @Test
    public void testForCopyContextDis1(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_dis_1.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
    /**
     * 测试对比orig.txt与orig_0.8_dis_10.txt
     */
    @Test
    public void testForCopyContextDis10(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_dis_10.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
    /**
     * 测试对比orig.txt与orig_0.8_dis_15.txt
     */
    @Test
    public void testForCopyContextDis15(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_dis_15.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
    /**
     * 测试相同文档对比
     */
    @Test
    public void testForSameContext(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }}
说明测试的方法,构造测试数据的思路
  -单元测试:针对各种不同数据的输入,以及路径参数的输入进行测试
测试结果

测试覆盖率

计算模块部分异常处理说明
针对IOException等文件写入和读取异常,需要进行处理
自定义异常

设计目的
- 出现IOException时,截取它,抛出自定义异常传递出现的异常信息
- 命令行参数出现错误时,截取,抛出自定义异常传递出现的异常信息
    /**
     * 测试原创论文路径为null的情况
     */
    @Test
    public void testForOriginalContextNull(){
        try {
            PaperCheckMain.process(null,"E:\\test\\orig_0.8_add.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            System.out.println("输入参数不能为空!");
        }
    }
    /**
     * 测试命令行参数输入错误
     */
    @Test
    public void testForErrorArgs(){
        try {
            PaperCheckMain.process("errorPath","E:\\test\\orig.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            System.out.println("命令行参数错误!");      
            e.printStackTrace();
        }
    }
PSP表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) | 
|---|---|---|---|
| Planning | 计划 | 30 | 40 | 
| · Estimate | · 估计这个任务需要多少时间 | 40 | 40 | 
| Development | 开发 | 300 | 320 | 
| · Analysis | · 需求分析 (包括学习新技术) | 30 | 40 | 
| · Design Spec | · 生成设计文档 | 60 | 80 | 
| · Design Review | · 设计复审 | 20 | 30 | 
| · Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 40 | 30 | 
| · Design | · 具体设计 | 30 | 30 | 
| · Coding | · 具体编码 | 200 | 220 | 
| · Code Review | · 代码复审 | 30 | 20 | 
| · Test | · 测试(自我测试,修改代码,提交修改) | 30 | 30 | 
| ·Reporting | 报告 | 60 | 60 | 
| · Test Repor | · 测试报告 | 30 | 30 | 
| · 合计 | 850 | 970 | 
 
                    
                




 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号