论文查重系统
github仓库地址:https://github.com/CageHuang1220/3124004056
学号:3124004056
| 这个作业属于哪个课程 | 计科24级56班 |
|---|---|
| 这个作业要求在哪里 | 个人工程 |
| 这个作业的目标 | 完成论文查重的程序设计 |
论文查重(Java)
学号:
3124004056
姓名:黄凯祺
语言:Java
构建工具:Maven
运行入口:main.jar
一、项目说明
本项目实现一个论文查重程序。程序从命令行接收三个文件路径:
java -jar main.jar [原文文件] [抄袭版论文文件] [答案文件]
程序读取原文和抄袭版论文,计算两者的重复率,并将结果写入答案文件。答案为一个 0.00 到 1.00 的浮点数,精确到小数点后两位。
例如:
java -jar target/main.jar sample_data/orig.txt sample_data/orig_add.txt sample_data/ans.txt
运行后 sample_data/ans.txt 内容为:
0.61
二、环境与构建
- JDK 8 或更高版本
- Maven 3.8 或更高版本
构建并运行测试:
mvn -s maven-settings.xml clean package
如果本机 Maven 全局配置可用,也可以直接使用 mvn clean package。这里的
maven-settings.xml 只是为了将本项目依赖缓存到当前目录下的 .m2,避免依赖
全局本地仓库。
生成的 jar 文件为:
target/main.jar
只运行测试:
mvn test
三、目录结构
.
├── pom.xml
├── README.md
├── sample_data
│ ├── orig.txt
│ └── orig_add.txt
└── src
├── main/java/com/luwenchachong
│ ├── Main.java
│ ├── TextFileIO.java
│ ├── TextSimilarity.java
│ ├── PlagiarismCheckException.java
│ ├── InvalidArgumentsException.java
│ ├── InputFileException.java
│ └── OutputFileException.java
└── test/java/com/luwenchachong
├── MainTest.java
└── TextSimilarityTest.java
四、计算模块设计
1. 模块划分
| 模块 | 职责 |
|---|---|
Main |
解析命令行参数,编排文件读取、相似度计算和答案写出 |
TextFileIO |
读取 UTF-8、UTF-16、GB18030、Big5 等常见编码文件,并写出答案 |
TextSimilarity |
文本归一化、字符二元组切分、词频向量构造和余弦相似度计算 |
PlagiarismCheckException 及子类 |
统一表达参数、输入、输出等可预期错误 |
2. 调用关系
Main.run(args)
├── TextFileIO.readInput(原文路径)
├── TextFileIO.readInput(抄袭版路径)
├── TextSimilarity.compare(原文, 抄袭版)
└── TextFileIO.writeAnswer(答案路径, 重复率)
3. 算法关键
中文文本没有天然词边界,因此本项目使用字符二元组(bigram)作为特征,统计词频后使用余弦相似度计算重复率。
处理过程:
- 去除 HTML 标签和常见 HTML 实体,降低网页复制文本的噪声。
- 使用 NFKC 归一化统一全角、半角字符,英文统一小写。
- 仅保留中文字符(Han 字符),去除标点、空白、英文和数字等噪声。
- 对每个字符二元组计数,构造稀疏词频向量。
- 使用余弦相似度计算两个向量的夹角相似度。
选择余弦相似度的原因:
- 对文本长度变化不敏感,适合“原文 + 增删改”的抄袭场景。
- 时间复杂度为线性,能够满足大文本的性能要求。
- 重复片段会被词频自然放大,比单纯集合交并集更符合重复率的含义。
五、性能改进
当前实现使用 HashMap<Long, Integer> 保存 bigram 词频。对于两篇长度为 n 和 m 的文本:
- 特征提取复杂度为
O(n + m)。 - 余弦点积遍历较小的向量,复杂度为
O(min(n, m))。 - 内存占用与不同 bigram 数量成正比,通常远低于 2048 MB 限制。
项目中包含一个长文本单元测试 longTextCompletesWithinTimeLimit,用于防止时间复杂度退化。经过 Maven 测试,17 个测试用例全部通过。
六、单元测试
测试框架使用 JUnit 5,测试文件:
TextSimilarityTest:覆盖完全相同、完全不同、中文标点空白差异、样例输入、增删改、单字、空文本、HTML 噪声、长文本等场景。MainTest:覆盖端到端输出格式、参数错误、文件不存在、输出目录不存在、GB18030 编码读取。
运行:
mvn test
当前测试结果:
Tests run: 17, Failures: 0, Errors: 0, Skipped: 0
七、异常处理
| 异常 | 触发场景 | 返回码 |
|---|---|---|
| 参数数量错误 | 命令行参数不是 3 个 | 2 |
| 输入文件不存在或不可读 | 原文或抄袭版路径错误、权限不足 | 3 |
| 文件编码无法识别 | 输入文件不是常见文本编码 | 3 |
| 答案文件无法写入 | 输出路径所在目录不存在、无写权限 | 4 |
| 未预期内部错误 | 其他运行时异常 | 1 |
所有可预期错误都会输出到标准错误流,并通过退出码表示失败原因,不会向答案文件写入脏数据。
八、PSP 表格
以下为本次项目的 PSP 2.1 记录。
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 30 | 25 |
| · Estimate | · 估计这个任务需要多少时间 | 30 | 25 |
| Development | 开发 | 300 | 320 |
| · Analysis | · 需求分析(包括学习新技术) | 45 | 40 |
| · Design Spec | · 生成设计文档 | 30 | 25 |
| · Design Review | · 设计复审 | 20 | 15 |
| · Coding Standard | · 代码规范 | 15 | 10 |
| · Design | · 具体设计 | 35 | 40 |
| · Coding | · 具体编码 | 90 | 110 |
| · Code Review | · 代码复审 | 25 | 30 |
| · Test | · 测试(自我测试,修改代码,提交修改) | 40 | 50 |
| Reporting | 报告 | 70 | 75 |
| · Test Report | · 测试报告 | 25 | 25 |
| · Size Measurement | · 计算工作量 | 15 | 10 |
| · Postmortem & Process Improvement Plan | · 事后总结,并提出过程改进计划 | 30 | 40 |
| 合计 | 400 | 420 |
九、代码质量说明
- 类名使用大驼峰,方法名使用小驼峰,命名具有业务含义。
- 核心类和方法带有简要注释,说明职责和边界。
- 所有编译警告已处理,Maven 构建和测试均可通过。
- 项目只读写命令行指定的三个文件,不连接网络,不读写额外文件。

浙公网安备 33010602011771号