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

222100235熊铃锋 2024-03-03 17:19:37
这个作业属于哪个课程2302软件工程社区
这个作业要求在哪里软件工程第二次作业--文件读取
这个作业的目标完成对世界游泳锦标赛跳水项目相关数据的收集,并实现一个能够对赛事数据进行统计的控制台程序
其他参考文献工程师的能力评估和发展阿里巴巴Java开发手册

目录

  • 1.Gitcode项目地址
  • 2.PSP表格
  • 3.解题思路描述
  • 3.1 总体思路流程图
  • 3.2 获取json数据
  • 3.3 解析json数据
  • 3.3 解析json文件
  • 3.4 步骤分析
  • 4.设计与实现过程
  • 4.1 组织结构和接口设计
  • 4.2 关键代码展示
  • 5.程序性能改进
  • 5.1 改进思路
  • 5.2 具体改进方法
  • 6.异常处理
  • 7.单元测试
  • 7.1 测试工具
  • 7.2测试类
  • 8.心路历程与收获

1.Gitcode项目地址

仓库地址:222100235

2.PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划3020
• Estimate• 估计这个任务需要多少时间3030
Development开发700630
• Analysis• 需求分析(包括学习新技术)180160
• Design Spec• 生成设计文档6060
• Design Review• 设计复审5050
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)4030
• Design• 具体设计100100
• Coding• 具体编码420400
• Code Review• 代码复审120100
• Test• 测试(自我测试,修改代码,提交修改)140120
Reporting报告120120
• Test Repor• 测试报告7060
• Size Measurement• 计算工作量7060
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划6050
合计21901990

3.解题思路描述

3.1 总体思路流程图

img

3.2 获取json数据

  • athletes数据获取

    打开世界游泳锦标赛官网,点开F12,再进入运动员界面,获取json数据

img

  • result数据获取

img

3.3 解析json数据

首先对json文件的结构进行分析
athletes.json

img


从athletes.json文件中,我们可以获得我们所需要的运动员信息
接着是event文件

img


img


获得Rank,FullName等信息

img


从赛事文件中,我们可以获得相关信息DivePoint,FullName,TotalPoint,Gender等

3.3 解析json文件

使用第三方库Gson对json文件进行解析,可以使用Map,List等方法存储对象信息,或者使用手动方法帮助解析并存储信息。
在使用Gson方法前,要设计一个json转String的方法getJsonString

3.4 步骤分析

1.读取input.txt:使用List将文件中的指令存储下来,交给控制器使用
2.识别并运行指令:控制器controller读取指令并识别,根据判断结果使用不同的操作函数
3.写入文件:不同的操作函数,使用StringBuilder将结果写入文件output.txt中

4.设计与实现过程

4.1 组织结构和接口设计

程序组织架构,程序由多个类组成,包括getAthletes()获得运动员信息,getResults()获得比赛信息,getEventDetail()获得比赛详细信息,使用接口设计,将这三个方法封装起来。outputPlayers()输出运动员信息,outputError()输出Error,outputNA()输出N/A,outputResult()输出比赛信息,outputEventDetail()输出比赛详细信息。

img


我的思路是,readInput()读取指令并保存在List中,控制器controller读取指令并判断,根据指令走向不同的分支,DataSourceIml()继承DataSource(),实现了获得信息的相关函数,通过DataSourceIml()获得信息后传给输出函数,最后写入output.txt中。
其中的关键在于解析Json获得数据,因此我使用第三方库Gson来帮助解析Json,手动导入Gson jar包,要想使用Gson的fromJso()方法将Json转化成对象,我需要写一个方法getJsonString()将Json文件转成字符串,将Json转成对象后,可以使用手动建类或者是使用List来存储对象,

4.2 关键代码展示

•分析json文件,获取字符串
getJsonString函数:
• 参数:json文件的路径
• 返回:json字符串
• 调用关系:被getAthletes(),getResults(),getEventDetail()函数调用;

public String getJsonString(String fileName) {
        try {
            File fp = new File(fileName);
            if (!fp.exists()) {
                fp.createNewFile();
            }
            String str;
            StringBuilder sb = new StringBuilder();
            //创建一个文件输入流,再创建一个BufferedReader对象,用来从文件输入流中读取数据
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fp), "UTF-8"));
            while ((str = reader.readLine()) != null) {
                sb.append(str);
            }
            reader.close();
            return sb.toString();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;

    }

•Gson解析字符串,获得运动员信息
getAtletes函数:
• 参数:无
• 返回:字符串

public String getAthletes() {

        //如果hashMap中已有运动员信息
        if (sites.containsKey("players")) {
            return sites.get("players");
        }
        //String S = getJsonString("D:\\File\\study\\codechina\\project-java\\222100235\\src\\data\\athletes.json");
        Gson gson = new Gson();
        List<AthletesData> athletesData = gson.fromJson(getJsonString(athletesPath), new TypeToken<List<AthletesData>>() {
        }.getType());
        StringBuilder sb = new StringBuilder();
        if (athletesData != null) {
            for (AthletesData athletesData1 : athletesData) {
                String country = athletesData1.getCountryName();
                List<Participation> participations = athletesData1.getParticipations();
                for (Participation part : participations) {
                    String gender = part.getGender() == 0 ? "Male" : "Female";
                    String firstName = part.getPreferredFirstName();
                    String lastName = part.getPreferredLastName();
                    sb.append("Full Name:" + lastName + " " + firstName + "\n");
                    sb.append("Gender:" + gender + "\n");
                    sb.append("Country:" + country + "\n");
                    sb.append("-----" + "\n");
                }

            }

        }
        sites.put("players", sb.toString());
        return sb.toString();
    }

•Gson解析字符串,获得比赛信息
getResults函数:
• 参数:指令字符串
• 返回:字符串

public String getResults (String cmd) {
            //如果hashMap中已有比赛信息
            if (sites.containsKey(cmd)) {
                return sites.get(cmd);
            }

            Gson gson = new Gson();
           // ResultData resultData = gson.fromJson(getJsonString(cmdNames.get(cmd)), ResultData.class);
            Map map = gson.fromJson(getJsonString(cmdNames.get(cmd)),Map.class);
            StringBuilder sb = new StringBuilder();
            List<Map> heat = (List<Map>)map.get("Heats");

            for(Map m : heat){
                List<Map> results = (List<Map>)m.get("Results");
                for (Map r : results){
                    double rank = (double) r.get("Rank");
                    sb.append("Full Name:" + r.get("FullName") + "\n");
                    sb.append("Rank:" + (int)rank + "\n");
                    sb.append("Score:");
                    List<Map> dives = (List<Map>)r.get("Dives");
                    List<String> points = new ArrayList<>();
                    int index = 0;
                    for (Map d : dives){
                        index++;
                        points.add((String) d.get("DivePoints"));
                    }
                    for (int i = 0;i < index;i++){
                        if (i < index - 1){
                            sb.append(points.get(i) + " + ");
                        }else {
                            sb.append(points.get(i) + " = ");
                        }
                    }
                    sb.append(r.get("TotalPoints") + "\n");
                    sb.append("-----" + "\n");
                }
            }
           sites.put(cmd, sb.toString());
            return sb.toString();

        }

5.程序性能改进

5.1 改进思路

首先是加快指令查找,使用HashMap存储指令与json文件路径的对应关系,方便快速查找。
接着使用HashMap记录指令与输出的关系,这样在有多个相同指令的情况下,避免程序重复执行,加快运行速度,减少频繁的文件读取次数。
另一个需要改进的地方是可以使用BufferdWriter包装FileWriter作输入流,提高运行速度。

5.2 具体改进方法

1.HashMap记录指令与Json文件的对应关系

static HashMap<String,String> cmdNames = new HashMap<String,String>(){
        {
            put("result men 1m springboard",resultPath6);
            put("result men 3m springboard",resultPath9);
            put("result men 3m synchronised",resultPath7);
            put("result men 10m platform",resultPath3);
            put("result men 10m synchronised",resultPath5);
            put("result women 1m springboard",resultPath4);
            put("result women 3m springboard",resultPath2);
            put("result women 3m synchronised",resultPath8);
            put("result women 10m platform",resultPath1);
            put("result women 10m synchronised",resultPath0);

            put("result men 1m springboard detail",resultPath6);
            put("result men 3m springboard detail",resultPath9);
            put("result men 3m synchronised detail",resultPath7);
            put("result men 10m platform detail",resultPath3);
            put("result men 10m synchronised detail",resultPath5);
            put("result women 1m springboard detail",resultPath4);
            put("result women 3m springboard detail",resultPath2);
            put("result women 3m synchronised detail",resultPath8);
            put("result women 10m platform detail",resultPath1);
            put("result women 10m synchronised detail",resultPath0);

        }
    };
  1. 使用HashMap记录指令与输出结果的对应关系
/*
    使用hashmap存储运动员和比赛信息
    "player = 运动员信息"
     */
    HashMap<String, String> sites = new HashMap<>();
    /*
    使用hashmap存储运动员信息
    帮助输出比赛详细信息
     */
    HashMap<String , AthleteClass> events = new HashMap<>();
  1. 使用BufferdWriter包装FileWriter作输入流
 //创建一个文件输入流,再创建一个BufferedReader对象,用来从文件输入流中读取数据
   BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fp), "UTF-8"));

6.异常处理

异常处理主要使用try...catch以及throw方法进行处理
输出函数中的异常处理

//输出Error
    public void outputError(String fileName){
        try{
        File fp = new File(fileName);
            if (!fp.exists()){
                fp.createNewFile();
            }
          ......
        }catch (IOException e){
            e.printStackTrace();
        }
    }

通过throw方法抛出异常,使用catch捕捉异常并处理

//读取input.txt文件内容,保存下来,准备下一步处理
    public List<String> readInput(String fileName){
        try{
            File fp = new File(fileName);
            if (!fp.exists()){
                throw new FileNotFoundException(fileName + "文件不存在");
            }
           ......
        } catch (FileNotFoundException exception){
            System.out.println(exception);
        } catch (IOException e){
            e.printStackTrace();
        }
        return null;
    }

7.单元测试

7.1 测试工具

使用JUint进行单元测试,首先下载JUint jar包,再手动导入。接着建立一个Test包,建立一个单元测试类进行测试。
测试时使用覆盖率运行测试类

img

7.2测试类

 @Test
    public void main() {
        //正确
        DWASearch.main(new String[]{"D:\\File\\study\\codechina\\project-java\\222100235\\src\\input.txt",
      "D:\\File\\study\\codechina\\project-java\\222100235\\src\\output.txt"});
    }
    @Test
    public void test(){
        //参数错误
        DWASearch.main(new String[]{"D:\\File\\study\\codechina\\project-java\\222100235\\src\\input.txt"});
    }
    @Test
    public void test1(){
        //参数错误
        DWASearch.main(new String[]{" ","D:\\File\\study\\codechina\\project-java\\222100235\\src\\input.txt"});
    }
    @Test
    public void test2(){
        //参数错误
        DWASearch.main(new String[]{" "," "," "});
    }

对参数错误的测试类测试结果如下:

img


由于参数错误,程序抛出并处理异常,输出“文件不存在”

对参数正确的测试类测试结果如下:
各种指令,包括输出运动员信息,比赛信息,比赛详细信息,Error,N/A

img


测试结果,由于新加入指令,HashMap中没有相应结果,因此覆盖的方法率高

img


多次运行后,覆盖的方法较少,覆盖率降低

img


因此,在第一次输入正确参数的情况下,测试通过,类的覆盖率达到百分百的同时也有较高的代码和方法覆盖率。

8.心路历程与收获

在本次实践过程中,我接触到了很多之前我不曾了解的知识,包括使用Gson解析Json文件,建立单元测试类,如何导入jar包等。在刚开始的过程中,完全不知道如何动手,来来回回参考了很多博客,查询了很多资料,学到了很多知识,好在最终完成了这个项目。在这次实践的过程中,我知道万事开头难,在开始动手编程前一定要对程序进行先一步的分析,了解要用到的知识,这样在编程的过程中才能游刃有余。接着,一定要根据PSP表格来对自己完成项目的每一步有一个时间上的规划,安排好时间,不然到后面就会很忙。

...全文
101 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

122

社区成员

发帖
与我相关
我的任务
社区描述
FZU-SE
软件工程 高校
社区管理员
  • LinQF39
  • 助教-吴可仪
  • 一杯时间
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧