个人项目
这个作业属于哪个课程 | 计科3班 |
---|---|
这个作业要求在哪里 | 作业要求 |
这个作业的目标 | <单元测试,代码性能,PSP表,git的正确使用 > |
Github
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 30 |
· Estimate | · 估计这个任务需要多少时间 | 10 | 10 |
Development | 开发 | 120 | 190 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 90 |
· Design Spec | · 生成设计文档 | 20 | 20 |
· Design Review | · 设计复审 | 10 | 10 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
· Design | · 具体设计 | 20 | 25 |
· Coding | · 具体编码 | 70 | 90 |
· Code Review | · 代码复审 | 20 | 40 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 100 |
Reporting | 报告 | 40 | 50 |
· Test Repor | · 测试报告 | 30 | 25 |
· Size Measurement | · 计算工作量 | 10 | 10 |
计算模块接口的设计与实现过程
流程
通过命令行获取文件路径,读取相应的文件内容
将文本转化为一个字符串
计算重复字数和重复率
将结果写入相应的文件中,没有文件则创建新文件写入
项目结构
项目中的类和功能
- Main:程序入口
- CalculatorUtil:核心算法相关的工具类
- 1)calculate():计算重复字数
- FileUtil:文件操作工具类
- 1)readFromFile():读取文件内容
- 2)writeInFile():将结果写入文件中
- 3)createFileIfNotExist():确保输出的目标文件存在
- 4)getPercentFormat():转换重复率
- File:论文文件模型
算法分析
如何计算
先计算出两篇论文中重复的字数,再除以对比论文的总字数,即:
- 重复率=重复字数/对比论文总字数
核心算法
其中计算重复字数的核心算法的是用动态规划实现最长公共子序列(LCS)算法
- 由于C[i,j]的值总是建立在二维数组第i行某一列元素或者第i-1行某一列元素基础上的,如果不需要求解最长公共子序列是什么,只需要求解其长度,那么可以建立一个2n的滚动数组代替nm的数组来实现空间优化,这种方法只需要用到两个数组的数据,通过两个数组的不断交换实现m*n的数组功能。
计算模块接口部分的性能
Telemetries
Live memory
Hot spots
单元测试展示
测试代码
public class TestMain {
/**
* 测试源文件路径为null的情况
*/
@Test
public void testForOriginalArticleNull(){
// Assert.assertThrows()
Main.main(new String[]{null,"D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig_0.8_add.txt","D:\\1.txt"});
}
/**
* 测试对比文件路径为null的情况
*/
@Test
public void testForPlagiarismArticleNull(){
Main.main(new String[]{"D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig.txt",null,"D:\\1.txt"});
}
/**
* 测试结果输出文件路径为null的情况
*/
@Test
public void testForResultNull(){
Main.main(new String[]{"D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig.txt","D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig_0.8_add.txt",null});
}
/**
* 测试路径不存在的情况
*/
@Test
public void testForNotExistFile(){
Main.main(new String[]{"D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\origno.txt","D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig_0.8_add.txt","D:\\1.txt"});
}
/**
* 测试输入对比的文件内容为空的情况
*/
@Test
public void testForEmpty(){
Main.main(new String[]{"D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig.txt","D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig_empty.txt","D:\\1.txt"});
}
/**
* 测试对比orig_0.8_add.txt
*/
@Test
public void testForAdd(){
Main.main(new String[]{"D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig.txt","D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig_0.8_add.txt","D:\\1.txt"});
}
/**
* 测试对比orig_0.8_del.txt
*/
@Test
public void testForDel(){
Main.main(new String[]{"D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig.txt","D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig_0.8_del.txt","D:\\1.txt"});
}
/**
* 测试对比orig_0.8_dis_1.txt.txt
*/
@Test
public void testForDis1(){
Main.main(new String[]{"D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig.txt","D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig_0.8_dis_1.txt","D:\\1.txt"});
}
/**
* 测试对比orig_0.8_dis_10.txt
*/
@Test
public void testForAdd10(){
Main.main(new String[]{"D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig.txt","D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig_0.8_dis_10.txt","D:\\1.txt"});
}
/**
* 测试对比orig_0.8_dis_15.txt
*/
@Test
public void testForDis15(){
Main.main(new String[]{"D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig.txt","D:\\gitcode\\acofGDUT\\3121004921\\homework\\Test\\resources\\orig_0.8_dis_15.txt","D:\\1.txt"});
}
}
测试结果
覆盖率
异常处理
空值处理
public class EnterNullException extends Exception {
public EnterNullException(){
}
public EnterNullException(String message){
super(message);
}
}
try {
if (args[0] == null){
throw new EnterNullException("输入的源文件地址为空,请重新输入!");
} else if (args[1] == null) {
throw new EnterNullException("输入的对比文件地址为空,请重新输入!");
}else if (args[2] == null){
throw new EnterNullException("输出文件地址为空,请重新输入!");
}
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
return;
}
测试
文件异常
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8));
// 一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null) {
builder.append(tempString.trim());
}
} catch (UnsupportedEncodingException e) {
System.out.println("目前不支持该编码格式,请更换其他编码格式!");
e.printStackTrace();
} catch (IOException e) {
if (e instanceof FileNotFoundException){
System.out.println("找不到该文件,请检查文件路径是否正确!");
}else {
System.out.println("读取文件异常!");
}
e.printStackTrace();
} finally {
if (reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}