这个作业属于哪个课程 | 202302软件工程实践 |
---|---|
这个作业要求在哪 | 软件工程第二次作业–文件读取 |
这个作业的目标 | 实现世界游泳锦标赛跳水项目相关赛事数据进行统计的一个控制台程序 |
参考文献 | 《构建之法》 |
文章目录
一.Gitcode项目地址
二.PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 40 |
• Estimate | • 估计这个任务需要多少时间 | 30 | 40 |
Development | 开发 | 1500 | 1400 |
• Analysis | • 需求分析 (包括学习新技术) | 400 | 300 |
• Design Spec | • 生成设计文档 | 200 | 200 |
• Design Review | • 设计复审 | 30 | 30 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 60 | 50 |
• Design | • 具体设计 | 30 | 40 |
• Coding | • 具体编码 | 300 | 250 |
• Code Review | • 代码复审 | 30 | 40 |
• MyTest | • 测试(自我测试,修改代码,提交修改) | 200 | 150 |
Reporting | 报告 | 60 | 50 |
• MyTest Report | • 测试报告 | 60 | 60 |
• Size Measurement | • 计算工作量 | 30 | 30 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 20 | 30 |
合计 | 2980 | 2710 |
三.思路描述
3.1、数据解析(Gson)
- 导入Gson包
- 设计相应的类用于接收json数据
- 编写解析器
- 创建Gson实例,执行操作
- 完成数据的解析
3.2、问题一
- 读取input.txt文件信息
try (BufferedReader inputReader = new BufferedReader(new FileReader(inputFileName)))
- 进行判断是否符合规则
if(line.equals(inputInfo.players))
- 读取json文件的数据
File file = new File("src\\main\\resources\\data\\players.json");
FileReader jsonReader = new FileReader(file);
- 创建Gson实例,解析数据到List中
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Player.class, new PlayerDeserializer());
Gson gson = builder.create();
TypeToken<List<Player>> type = new TypeToken<>() {
};
List<Player> players = gson.fromJson(jsonReader, type);
- 将List的信息写入output文件
try(BufferedWriter writer = new BufferedWriter(new FileWriter(outputFileName,true))){
for(Player player :players){
writer.write("Full Name:"+player.fullName);
writer.newLine();
writer.write("Gender:"+player.gender);
writer.newLine();
writer.write("Country:"+player.country);
writer.newLine();
writer.write("-----");
writer.newLine();
}
}
3.2、问题二
- 判断input中的信息
else if(line.equals("result "+inputInfo.m1sb))
- 读取json文件
FileReader reader = new FileReader(this.jsonFile);
- 创建gson实例
Gson gson = new GsonBuilder()
.registerTypeAdapter(Competition.class, new CompetitionDeserializer())
.create();
- 输出到output文件中
try(BufferedWriter writer = new BufferedWriter(new FileWriter(outputFileName,true))){
for(PlayerResult playerResult : finalResults){
writer.write("Full Name:"+playerResult.getPlayerFullName());
writer.newLine();
writer.write("Rank:"+playerResult.getRank());
writer.newLine();
writer.write("Score:"+playerResult.getDivePoints().get("1")+" + "+playerResult.getDivePoints().get("2")+" + "+playerResult.getDivePoints().get("3")+" + "+playerResult.getDivePoints().get("4")+" + "+playerResult.getDivePoints().get("5")+" + "+playerResult.getDivePoints().get("6"));
writer.newLine();
writer.write("-----");
writer.newLine();
}
}
四、接口设计和实现过程
4.1、类的设计
- Main类:主要的逻辑代码
- Player类:用来存放json解析后的运动员信息
- PlayerDeserializer类:json解析器
- Competition和PlayerResult类:存放总决赛和半决赛的信息
- PrintMethod类:封装一个打印函数,便于调用
五、关键代码展示
打印函数
public void print(){
try {
if(this.finalResults==null){
// 创建 Gson 对象,并设置适当的反序列化器
Gson gson = new GsonBuilder()
.registerTypeAdapter(Competition.class, new CompetitionDeserializer())
.create();
// 使用 FileReader 读取 JSON 数据
FileReader reader = new FileReader(this.jsonFile);
// 将 JSON 数据转换为 Competition 对象
Competition competition = gson.fromJson(reader, Competition.class);
// 访问 finalResults
this.finalResults = competition.getFinalResults();
try(BufferedWriter writer = new BufferedWriter(new FileWriter(outputFileName,true))){
for(PlayerResult playerResult : finalResults){
writer.write("Full Name:"+playerResult.getPlayerFullName());
writer.newLine();
writer.write("Rank:"+playerResult.getRank());
writer.newLine();
writer.write("Score:"+playerResult.getDivePoints().get("1")+" + "+playerResult.getDivePoints().get("2")+" + "+playerResult.getDivePoints().get("3")+" + "+playerResult.getDivePoints().get("4")+" + "+playerResult.getDivePoints().get("5")+" + "+playerResult.getDivePoints().get("6"));
writer.newLine();
writer.write("-----");
writer.newLine();
}
}
}else{
try(BufferedWriter writer = new BufferedWriter(new FileWriter(outputFileName,true))){
for(PlayerResult playerResult : finalResults){
writer.write("Full Name:"+playerResult.getPlayerFullName());
writer.newLine();
writer.write("Rank:"+playerResult.getRank());
writer.newLine();
writer.write("Score:"+playerResult.getDivePoints().get("1")+" + "+playerResult.getDivePoints().get("2")+" + "+playerResult.getDivePoints().get("3")+" + "+playerResult.getDivePoints().get("4")+" + "+playerResult.getDivePoints().get("5")+" + "+playerResult.getDivePoints().get("6"));
writer.newLine();
writer.write("-----");
writer.newLine();
}
}
}
//将finalResult的结果写入output.txt中
} catch (IOException e) {
throw new RuntimeException(e);
}
}
六、性能改进
使用缓存,大大提高了效率:
private List<PlayerResult> finalResults;
if(this.finalResults==null){
}else{
}
七、单元测试
对main类进行单元测试,代码和结果如下:
public class MainTest3 {
@Test
void testMainMethod() throws IOException {
// 创建 Main 类对象
Main main = new Main();
// 准备测试所需的参数
String inputFileName = "input.txt";
String outputFileName = "output.txt";
File outputFile = new File(outputFileName);
outputFile.createNewFile();
//清空输出文件
try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputFileName))) {
writer.write(""); // 写入数据
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
}
// 创建一个测试输入文件 input.txt
File inputFile = new File(inputFileName);
try {
inputFile.createNewFile();
List<String> data=new ArrayList<>();
data.add("result ss");
data.add("ss");
data.add("result ss");
data.add("sab");
data.add("result ss");
data.add("sasb");
data.add("result ss");
data.add("");
data.add("result ss");
data.add("detail");
// 尝试写入数据到文件
try (BufferedWriter writer = new BufferedWriter(new FileWriter(inputFileName))) {
for(int i=0;i<10;i++){
writer.write(data.get(i));
writer.newLine();
}
System.out.println("数据已写入文件: " + data);
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
List<String> result=new ArrayList<>();
result.add("N/A-----");
result.add("ERROR-----");
result.add("N/A-----");
result.add("ERROR-----");
result.add("N/A-----");
result.add("ERROR-----");
result.add("N/A-----");
result.add("ERROR-----");
result.add("N/A-----");
result.add("ERROR-----");
// 运行 main 方法
main.main(new String[]{inputFileName, outputFileName});
String line;
try (BufferedReader reader = new BufferedReader(new FileReader(outputFile))) {
for(int i=0;i<10;i++){
line= reader.readLine();
assertEquals(line,result.get(i));
}
}
}
测试结果
八、异常处理
参数校验
if (args.length != 2) {
System.out.println("请正确输入参数");
return;
}
I/O异常
} catch (IOException e) {
System.err.println("发生IO异常: " + e.getMessage());
}
九、心得体会
在完成这个文件读取的作业过程中,我学到了如何使用 Java 中的文件读写功能以及如何使用 Gson 库来处理 JSON 数据。通过这个作业,我更加熟悉了如何使用 Java 的输入输出流来进行文件读写操作。这对于处理各种数据文件是非常重要的,尤其是在处理大量数据时。在文件读写过程中,我意识到了异常处理的重要性。通过使用 Gson 库,我学会了如何将 JSON 数据转换为 Java 对象,并且在程序中进行处理和操作。这为我提供了一种方便快捷的方法来处理各种类型的数据文件,尤其是 JSON 格式的数据。在开发过程中,我实践了单元测试的重要性。编写单元测试有助于验证代码的正确性,尤其是在处理文件读写等涉及外部资源的操作时。通过单元测试,我可以更自信地确保代码的质量和可靠性。