• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
order-god
博客园    首页    新随笔    联系   管理    订阅  订阅
第一次个人编程作业
  • Github链接
这个作业属于那个课程 软件工程-计科21级12班
这个作业要求在哪里 个人项目
这个作业的目标 使用Java设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率

一、PSP表格

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

二、模块接口的设计与实现过程

总体设计

依赖

JUnit测试以及Logback日志依赖

工具类

IOUtils

  • 读取文件内容方法:readFileContent
    • 使用字符缓冲流读取数据,文件路径有误则使用日志在控制台输出问题
  • 写入文件内容方法:writeFileContent
    • 使用字符缓冲流写入数据,文件路径有误则使用日志在控制台输出问题

CheckUtils

  • 计算字符串相似度方法:calculateSimilarity

    • 算法介绍

      • 使用 Levenshtein 距离算法,也称为编辑距离算法,是一种用于衡量两个字符串之间差异程度的度量方法。它通过计算将一个字符串转换为另一个字符串所需的最少编辑操作次数来量化字符串之间的差异

      • 动态规划思想:Levenshtein距离算法使用动态规划的思想,通过构建一个二维矩阵来处理字符串比较问题。

      • 状态转移方程:算法通过迭代更新矩阵中的值,以获得最小编辑距离。状态转移方程如下:

        dp[i][j] = min(dp[i-1][j-1] + cost, dp[i-1][j] + 1, dp[i][j-1] + 1);
        

        其中dp[i] [j]表示字符串1的前i个字符与字符串2的前j个字符之间的编辑距离,cost表示第i和第j个字符是否匹配,若不匹配则cost为1,否则为0。min表示取三个参数的最小值。

      • 初始化操作:将矩阵的第一行和第一列初始化为对应的索引值,因为将一个字符串转换为空字符串或反之所需的编辑操作次数等于索引值。

      • 计算最小编辑距离:迭代填充矩阵,并获取矩阵的右下角元素的值,即为字符串的最小编辑距离。

    • 算法独到之处

      • 灵活性:算法可以用于不同类型的字符串,包括文本、代码和其他形式的数据。它不依赖于特定的领域知识,因此适用于各种应用场景。
      • 不敏感性:与其他相似度度量方法相比,Levenshtein距离算法对字符串的长度变化和字符顺序的变化不敏感。它关注的是字符的匹配和替换,而不考虑它们的位置。
      • 适应性:Levenshtein距离算法可以根据需求进行扩展和定制。根据编辑操作的成本和约束条件,可以修改状态转移方程,以便更精确地度量字符串之间的差异。

三、模块接口部分的性能改进

使用Intellij Profiler分析性能

四、模块部分单元测试展示

readFileContentTest1

  • 代码:

    @Test
    public void readFileContentTest1() {
        // 读取文本内容测试
        IOUtils.readFileContent("D:\\HYHAO\\Documents\\duplication-check\\3121004860\\duplication-check\\src\\main\\resources\\orig.txt");
    }
    
    • 测试方法:IOUtils.readFileContent
    • 测试覆盖率:

readFileContentTest2

  • 代码:

    @Test
    public void readFileContentTest2() {
        // 读取文本内容测试
        IOUtils.readFileContent("orig.txt");
    }
    
    • 测试方法:IOUtils.readFileContent
    • 测试覆盖率:

writeFileContentTest

  • 代码:

    @Test
    public void writeFileContentTest() {
        // 写入文本内容测试
        IOUtils.writeFileContent("D:\\HYHAO\\Documents\\duplication-check\\3121004860\\duplication-check\\src\\main\\resources\\target.txt", "hello");
    }
    
    • 测试方法:IOUtils.writeFileContent
    • 测试覆盖率:

CheckUtilsTest

  • 代码:

    @Test
    public void calculateSimilarityTest() {
        // 计算文本内容相似度测试
        String orig = "D:\\HYHAO\\Documents\\duplication-check\\3121004860\\duplication-check\\src\\main\\resources\\orig.txt";
        String target = "D:\\HYHAO\\Documents\\duplication-check\\3121004860\\duplication-check\\src\\main\\resources\\target.txt";
        String imit1 = "D:\\HYHAO\\Documents\\duplication-check\\3121004860\\duplication-check\\src\\main\\resources\\orig_0.8_add.txt";
        String imit2 = "D:\\HYHAO\\Documents\\duplication-check\\3121004860\\duplication-check\\src\\main\\resources\\orig_0.8_del.txt";
        String imit3 = "D:\\HYHAO\\Documents\\duplication-check\\3121004860\\duplication-check\\src\\main\\resources\\orig_0.8_dis_1.txt";
        String imit4 = "D:\\HYHAO\\Documents\\duplication-check\\3121004860\\duplication-check\\src\\main\\resources\\orig_0.8_dis_10.txt";
        String imit5 = "D:\\HYHAO\\Documents\\duplication-check\\3121004860\\duplication-check\\src\\main\\resources\\orig_0.8_dis_15.txt";
    
        // 定义一个抄袭论文集合
        List<String> imits = new ArrayList<>();
    
        // 将抄袭论文添加到集合中
        Collections.addAll(imits, imit1, imit2, imit3, imit4, imit5);
        for (String imit : imits) {
            // 计算相似度并写入target文件中
            double result = CheckUtils.calculateSimilarity(IOUtils.readFileContent(orig), IOUtils.readFileContent(imit));
            String message = "文件 " + imit + " 查重率为:" + String.format("%.2f", result);
            System.out.println(message);
            IOUtils.writeFileContent(target, message);
        }
    }
    
    • 测试函数:CheckUtils.calculateSimilarity
    • 测试覆盖率:

五、模块部分异常处理说明

IO读写异常处理

try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
    String line;
    while ((line = reader.readLine()) != null) {
        content.append(line).append("\n");
    }
} catch (IOException e) {
    LOGGER.error("文件读取失败...");
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) {
    writer.write(message);
    writer.newLine();
    writer.flush();
} catch (IOException e) {
    LOGGER.error("打开文件失败...");
}

命令行参数输入异常处理

if (args.length != 3) {
    LOGGER.error("命令行输入参数个数有误...");
} else {
    for (String arg : args) {
        if (!arg.endsWith("txt")) {
            LOGGER.error("命令行输入参数文本类型有误...");
            return;
        }
    }
}
posted on 2023-09-16 20:55  hyhao  阅读(69)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3