软件工程第二次作业–文件读取

这个作业属于哪个课程软件工程实践2023年W班
这个作业要求在哪里软件工程实践第二次作业——个人实战
这个作业的目标完成对世界游泳锦标赛跳水项目相关数据的收集,并实现一个能够对赛事数据进行统计的控制台程序
其他参考文献

1、Gitcode项目地址

我的gitcode仓库

2、PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划3040
• Estimate• 估计这个任务需要多少时间1010
Development开发10001230
• Analysis• 需求分析(包括学习新技术)3030
• Design Spec• 生成设计文档1510
• Design Review• 设计复审1015
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)3030
• Design• 具体设计7080
• Coding• 具体编码700780
• Code Review• 代码复审3540
• Test• 测试(自我测试,修改代码,提交修改)100220
Reporting报告6090
• Test Repor• 测试报告3040
• Size Measurement• 计算工作量1010
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划2015
合计10901360

3、解题思路描述

3.1对JSON文件解析

先将JSON文件保存在字符串中,再对字符串数据处理。导入fastjson的jar包,使用JSON.parseObject(string),JSONObject.getJSONArray(key),JSONObject.getString(key)等API实现对所需对象数据的查找

3.2实现功能1:输出所有选手信息

判断输入指令为players,使用 StringBuilder 存储输出内容,读取data文件后查找每一位选手对应的CountryName,PreferredLastName,Gender,并按照题目要求的格式append在StringBuilder,遍历完毕将获得的完整StringBuilder统一输出。

3.3实现功能2:输出决赛运动项目结果

实现了一个getid方法在event.json文件中查找到赛事名称相对应的赛事id,接着打开与id对应名字相等的result.json文件。依次读取获得每一场比赛的赛事信息,如果result.containsKey(“Competitors”)则为双人赛事,把双人选手的名字更改为题目要求的格式,再按照格式把选手的比赛情况依次写入StringBuilder中,当全部遍历结束,所获得的字符串整体直接写入到输出文件里。

3.4实现附加功能:输出详细结果

我用的是hashmap来存储比赛信息,key设置为选手名,value设置为Result对象。Result中存储着选手单个项目的所有赛事表现,方便更改特定选手的初赛半决赛决赛排名和分数。
算法是按照初赛-半决赛-决赛的顺序依次查找赛事结果的,当遍历到一位选手的时候,如果hashmap中对应key是不存在的,创建新Result,对初赛(半决赛)(决赛)赋值。由Hashmap.put(key,value)会直接替换之前对象的数据,导致成绩丢失,如果之前就已经有被赋值过的Result(比如在遍历半决赛阶段发现选手已经被赋值决赛成绩了)则直接修改Result的成绩,以此保证之前成绩不丢失。
遍历结束取出hashmap的ResultArrayList,按照PreliminaryRank排序后输出。

4、接口设计和实现过程

4.1 Instrusct

用于处理指令
DoInstrusct(String instr,String path)用于执行input文件里的每一条指令。
capitalizeWords(String instr)用于处理输入的指令,将符合要求的指令转换为可识别的字符串。

4.2 FileTool

用于io
readJson(String filename)读取json文件转换为字符串。
readFiles(String filename)用于读取input中的所有指令。
writeFiles(String filename, String output)用于输出结果到output。

4.3JsonRead

直接处理JSON字符串,是项目的功能核心
ShowPlayer(String filename,String path)获取所有运动员信息
getid(String DisciplineName)获取决赛赛事Id
showFinalResult(String disciplineName,String path)获取所需决赛信息
DealDoubleDive(JSONObject result)判断处理双人赛事,返回名字字符串
DetailedResults(String disciplineName,String path)获取赛事所有详细信息

5、关键代码展示

5.1 输出所有Player信息

 public static void ShowPlayer(String filename,String path) {
        FileTool ft = new FileTool();
        String jsonStr;
        jsonStr = ft.readJson(filename);
        JSONArray countriesArray = JSON.parseArray(jsonStr);
        StringBuilder output = new StringBuilder(); // 使用 StringBuilder 存储输出内容
        for (Object countryObj : countriesArray) {
            JSONObject countryJson = (JSONObject) countryObj;

            // 输出国家名称
            String countryName = countryJson.getString("CountryName");
            // 输出该国家的运动员信息
            JSONArray participations = countryJson.getJSONArray("Participations");
            for (Object obj : participations) {
                JSONObject participation = (JSONObject) obj;
                // 输出运动员信息
                String fullName = participation.getString("PreferredLastName") + " " + participation.getString("PreferredFirstName");
                String gender = participation.getInteger("Gender") == 0 ? "Male" : "Female";
                String nat = participation.getString("NAT");

                output.append("Full Name:").append(fullName).append("\n");
                output.append("Gender:").append(gender).append("\n");
                output.append("Country:").append(nat).append("\n");
                output.append("-----\n");
            }
        }
        ft.writeFiles(path, output.toString()); // 将输出内容写入文件
    }

5.2输出决赛信息

 public static void showFinalResult(String disciplineName,String path) {
        String id = getid(disciplineName);
        FileTool ff = new FileTool();
        String resultPath = "src/data/results/" + id + ".json";
        String jsonStr = ff.readJson(resultPath);
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        JSONArray heats = jsonObject.getJSONArray("Heats");

        StringBuilder output = new StringBuilder(); // 使用 StringBuilder 存储输出内容

        for (int i = 0; i < heats.size(); i++) {
            JSONObject heat = heats.getJSONObject(i);
            /*判断是否为决赛*/
            if ("Final".equals(heat.getString("Name"))) {
                JSONArray results = heat.getJSONArray("Results");
                for (int j = 0; j < results.size(); j++) {
                    JSONObject result = results.getJSONObject(j);
                    String fullName = result.getString("FullName");
                    String rank = result.getString("Rank");
                    String totalPoints = result.getString("TotalPoints");
                    List<String> score = new ArrayList<>();
                    JSONArray dives = result.getJSONArray("Dives");
                    for (int k = 0; k < dives.size(); k++) {
                        JSONObject oneScore = dives.getJSONObject(k);
                        String EachScore = oneScore.getString("DivePoints");
                        score.add(EachScore);
                    }
                    output.append("Full Name:").append(DealDoubleDive(result)).append("\n");
                    output.append("Rank:").append(rank).append("\n");
                    for (int k = 0; k < score.size() - 1; k++) {
                        output.append(score.get(i)).append("+");
                    }
                    output.append(score.get(score.size() - 1)).append("=").append(totalPoints).append("\n");
                    output.append("-----\n");
                }
            }
        }
        ff.writeFiles(path, output.toString()); // 将输出内容写入文件
    }

5.3输出赛事详细信息

public static List<Result>DetailedResults(String disciplineName,String path){
        String id = getid(disciplineName);
        FileTool ff = new FileTool();
        String resultPath = "src/data/results/" + id + ".json";
        String jsonStr = ff.readJson(resultPath);
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        JSONArray Heats=jsonObject.getJSONArray("Heats");
        Map<String,Result>drs=new HashMap<String, Result>();
        for(int i=0;i<Heats.size();i++) {
            JSONObject heat=Heats.getJSONObject(i);
            /*初赛成绩*/
            if("Preliminary".equals(heat.getString("Name"))){
                JSONArray Results=heat.getJSONArray("Results");
                for(int j=0;j<Results.size();j++){
                    JSONObject result=Results.getJSONObject(j);
                    Result rs=new Result();
                   // String fullname=result.getString("FullName");
                    String fullname=DealDoubleDive(result);
                    String rank = result.getString("Rank");
                    List<String>score=new ArrayList<>();
                    JSONArray dives=result.getJSONArray("Dives");
                    /*添加分数*/
                    for (int k = 0; k < dives.size(); k++) {
                        JSONObject oneScore=dives.getJSONObject(k);
                        String EachScore=oneScore.getString("DivePoints");
                        score.add(EachScore);
                    }
                    rs.setFullName(fullname);
                    rs.setPreliminaryRankRank(rank);
                    rs.setPreliminaryScore(score);
                    /*如果已经存在该选手,则直接修改,以此保证之前成绩不丢失*/
                    if(drs.containsKey(fullname)){
                        Result r=drs.get(fullname);
                        r.setPreliminaryRankRank(rank);
                        r.setPreliminaryScore(score);
                        drs.put(fullname,r);

                    }
                    /*否则创建新数据*/
                    else{drs.put(fullname,rs);}
                }
            }
            /*半决赛成绩*/
            else if("Semifinal".equals(heat.getString("Name"))){
                JSONArray Results=heat.getJSONArray("Results");
                for(int j=0;j<Results.size();j++){
                    JSONObject result=Results.getJSONObject(j);
                    Result rs=new Result();
                    //String fullname=result.getString("FullName");
                    String fullname=DealDoubleDive(result);
                    String rank = result.getString("Rank");
                    List<String>score=new ArrayList<>();
                    JSONArray dives=result.getJSONArray("Dives");
                    /*添加分数*/
                    for (int k = 0; k < dives.size(); k++) {
                        JSONObject oneScore=dives.getJSONObject(k);
                        String EachScore=oneScore.getString("DivePoints");
                        score.add(EachScore);
                    }
                    rs.setFullName(fullname);
                    rs.setSemiFinalRank(rank);
                    rs.setSemiminaryScore(score);
                    if(drs.containsKey(fullname)){
                        Result r=drs.get(fullname);
                        r.setSemiFinalRank(rank);
                        r.setSemiminaryScore(score);
                        drs.put(fullname,r);

                    }
                    else{
                        drs.put(fullname,rs);
                    }
                }
            }
            else if("Final".equals(heat.getString("Name"))){
                JSONArray Results=heat.getJSONArray("Results");
                for(int j=0;j<Results.size();j++){
                    JSONObject result=Results.getJSONObject(j);
                    Result rs=new Result();
                    //String fullname=result.getString("FullName");
                    String fullname=DealDoubleDive(result);
                    String rank = result.getString("Rank");
                    List<String>score=new ArrayList<>();
                    JSONArray dives=result.getJSONArray("Dives");
                    /*添加分数*/
                    for (int k = 0; k < dives.size(); k++) {
                        JSONObject oneScore=dives.getJSONObject(k);
                        String EachScore=oneScore.getString("DivePoints");
                        score.add(EachScore);
                    }
                    rs.setFullName(fullname);
                    rs.setFinalRank(rank);
                    rs.setFinalScore(score);
                    if(drs.containsKey(fullname)){
                        Result r=drs.get(fullname);
                        r.setFinalRank(rank);
                        r.setFinalScore(score);
                        drs.put(fullname,r);

                    }
                    else{
                        drs.put(fullname,rs);
                    }
                }
            }
        }

5.4执行指令

 public void DoInstrusct(String instr,String path) {
        // 检查指令是否包含大写字母
        if (instr.equals(instr.toLowerCase())) {
            if (instr.equals("players")) {
                /*执行player*/
                JsonRead jr=new JsonRead();
                jr.ShowPlayer("src/data/athletes.json",path);
            } else if (instr.startsWith("result")) {
                String resultInstruction = instr.substring(7).trim(); // 跳过 "result",获取后面的部分

                /*执行showFinalResult*/
                if (resultInstruction.matches("(women|m(men)) (1m springboard|3m springboard|10m platform|3m synchronised|10m synchronised)")) {
                    JsonRead jr=new JsonRead();
                    jr.showFinalResult(capitalizeWords(resultInstruction),path);
                }
                /*执行DetailedResults*/
                else if (resultInstruction.matches("(women|m(men)) (1m springboard|3m springboard|10m platform|3m synchronised|10m synchronised) detail")) {
                    JsonRead jr = new JsonRead();
                    jr.DetailedResults(capitalizeWords(resultInstruction),path);
                } else {
                    FileTool ff=new FileTool();
                    ff.writeFiles(path,"N/A");
                    System.out.println("N/A");
                }
            } else {
                FileTool ff=new FileTool();
                ff.writeFiles(path,"Error");
                System.out.println("Error");
            }
        } else {
           /* 如果指令包含大写字母,则输出 Error*/
            FileTool ff=new FileTool();
            ff.writeFiles("output.txt","Error");
            System.out.println("Error");
        }
    }

6、性能分析

我的代码在 ShowPlayer 和 showFinalResult 方法中,每次都在循环中读取文件。改进的时候把文件读取操作移出循环了,只在方法开始时读取一次文件并将结果保存在内存中,然后在循环中直接使用内存中的数据。
同样是 ShowPlayer 和 showFinalResult 方法中,刚开始想着StringBuilder 来拼接字符串可以使用append直接拼接字符串,没考虑到在循环中频繁地进行字符串拼接会影响性能。所以优化的时候使用String.join() 方法这种更高效的字符串拼接方式,以此提高性能。

修改前测试
在这里插入图片描述
修改后测试

在这里插入图片描述

7、单元测试

对核心模块中的detailedResults()和showFinalResult()两个方法进行测试,下面是一些测试数据


    @org.junit.jupiter.api.Test
    void showFinalResult1() {
        JsonRead.showFinalResult("Women 1m Springboard","output.txt");

    }
    @org.junit.jupiter.api.Test
    void showFinalResult2() {
        JsonRead.showFinalResult("Men 1m Springboard","output.txt");
    }
    @org.junit.jupiter.api.Test
    void showFinalResult3() {
        JsonRead.showFinalResult("Men 3m Springboard","output.txt");
    }
    @org.junit.jupiter.api.Test
    void showFinalResult4() {
        JsonRead.showFinalResult("Women 10m Platform","output.txt");
    }
    @org.junit.jupiter.api.Test
    void showFinalResult5() {
        JsonRead.showFinalResult("Men 10m Platform","output.txt");
    }

    @org.junit.jupiter.api.Test
    void detailedResults1() {
        JsonRead.DetailedResults("Men 10m Platform","output.txt");
    }
    @org.junit.jupiter.api.Test
    void detailedResults2() {
        JsonRead.DetailedResults("Women 1m Springboard","output.txt");
    }
    @org.junit.jupiter.api.Test
    void detailedResults3() {
        JsonRead.DetailedResults("Men 1m Springboard","output.txt");
    }
    @org.junit.jupiter.api.Test
    void detailedResults4() {
        JsonRead.DetailedResults("Men 3m Springboard","output.txt");
    }
    @org.junit.jupiter.api.Test
    void detailedResults5() {
        JsonRead.DetailedResults("Women 10m Platform","output.txt");
    }

以下是测试截图
在这里插入图片描述
核心模块的覆盖率
在这里插入图片描述
对DWASearch主类进行单元测试

在这里插入图片描述
ps:不知道为什么不写Main不让我过,主类在DWASearch,这里只是占个位。

8、异常处理

当发现文件打开异常时候,控制台输出提示信息,捕获异常

public List<String> readFiles(String filename) {
        List<String> instruct = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
            String line;
            while ((line = reader.readLine()) != null) {
                instruct.add(line); // 将每一行添加到List中
            }
            return instruct;
        } catch (IOException e) {
            System.out.println("发生错误!无法打开文件。");
            e.printStackTrace();
        }
        return null;
    }

当发现文件写入异常时候,控制台输出提示信息,捕获异常

    public void writeFiles(String filename, String output) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename, true))) {
            writer.write(output); // 将内容追加到文件末尾
        } catch (IOException e) {
            System.out.println("发生错误!无法写入文件。");
        }
    }

9、心得体会

这一次实践我学会了解析JSON,更加熟练文件的输入输出还有markdown文档的编写了!也在努力了解一些主流的代码规范。虽然现在的代码规范还是比较差,不太美观希望以后能慢慢养成习惯。通过不断地学习和实践,我相信我可以在未来的项目中更加游刃有余地处理各种挑战,不断提升自己的技术水平和解决问题的能力。

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值