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

该文章详细描述了一项关于软件工程的作业,涉及使用FastJSON库解析澳大利亚网球公开赛数据,实现文件读取和控制台程序,利用缓存机制提高性能,以及进行单元测试和异常处理。作业中,作者通过分析JSON数据,设计接口和程序流程,实现了对球员和比赛结果的处理,并分享了学习体会。
摘要由CSDN通过智能技术生成
这个作业属于哪个课程软件工程-23年春季学期
这个作业的要求在哪里软件工程实践第二次作业—文件读取
这个作业的目标完成对澳大利亚网球公开赛相关数据的收集,并实现一个能够对赛事数据进行统计的控制台程序
其他参考文献《构建之法》

GitCode项目地址

仓库地址

PSP表格

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

解题思路描述

获取JSON数据

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解析JSON数据

在这里插入图片描述
获取players的数据

在这里插入图片描述
在这里插入图片描述
获取results的数据

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

接口设计和实现过程

​Java中有三个解析JSON的主流类库:FastJSON、Gson和Jackson,这里采用FastJSON来对JSON数据进行解析,三个类库的性能对比详见三个主流的JSON解析库对比

接口设计

在这里插入图片描述

程序流程

在这里插入图片描述

关键代码展示

main()方法 ---- 接收指令并判断指令正误,执行对应指令

  public static void main(String[] args) {
        //创建缓存对象
        Cache<String, String> cache = Caffeine.newBuilder().initialCapacity(5).maximumSize(19).expireAfterWrite(17, TimeUnit.SECONDS).build();

        //命令行输入指令
        if (args.length != 2) {
            try {
                throw new Exception("输入指令格式有误");
            } catch (Exception e) {
                e.printStackTrace();
                return; //指令错误,终止程序
            }
        }
        String inputFile = args[0]; //输入文件
        String outputFile = args[1]; //输出文件

        //清空原文件的内容
        File file = new File(outputFile);
        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(file); //文件不存在时则会自动创建
            fileWriter.write(""); //清空
        } catch (IOException e) {
            e.printStackTrace();
        }

        //分析指令
        List<String> cmd = null;
        try {
            cmd = Lib.getInput(inputFile);
        } catch (Exception e) {
            e.printStackTrace();
            return; //输入文件不存在,终止程序
        }
        //解析每行指令
        for (String s : cmd) {
            if (s.isEmpty()) { //空行直接跳过不用处理
                continue;
            }
            s = s.trim(); //清空指令前后的空格
            if ("players".equals(s)) { //players指令
                String playersInfo;
                if (cache.getIfPresent(s) == null) { //如果缓存中没有这条指令则将其存入缓存
                    playersInfo = Lib.showPlayers(Lib.readJsonFile(Lib.PLAYERS_JSON));
                    cache.put(s, playersInfo);
                } else { //如果缓存中存在这条指令则从缓存中获取
                    playersInfo = cache.getIfPresent(s);
                }
                Lib.setOutput(outputFile, playersInfo);
            } else { //下一轮筛选
                String[] arr = s.split(" ");
                if ("result".equals(arr[0])) { //输入了result
                    if (arr.length != 2) { //输入的指令个数不对
                        StringBuffer naMeg = new StringBuffer();
                        naMeg.append("N/A\n");
                        naMeg.append("-----\n");
                        Lib.setOutput(outputFile, naMeg.toString());
                        continue;
                    } else { //指令个数为2
                        String jsonFile = Lib.RESULT_JSON + arr[1] + ".json";
                        String resultsInfo;

                        //判断文件是否存在
                        File f = new File(jsonFile);
                        if (!f.exists()) { //如果文件不存在
                            StringBuffer naMeg = new StringBuffer();
                            naMeg.append("N/A\n");
                            naMeg.append("-----\n");
                            Lib.setOutput(outputFile, naMeg.toString());
                            continue;
                        }

                        //使用缓存优化读取JSON数据
                        if (cache.getIfPresent(s) == null) {
                            resultsInfo = Lib.showResult(Lib.readJsonFile(jsonFile));
                            cache.put(s, resultsInfo);
                        } else {
                            resultsInfo = cache.getIfPresent(s);
                        }
                        Lib.setOutput(outputFile, resultsInfo);
                    }
                } else { //输入了错误的指令
                    StringBuffer errorMsg = new StringBuffer();
                    errorMsg.append("Error\n");
                    errorMsg.append("-----\n");
                    Lib.setOutput(outputFile, errorMsg.toString());
                }
            }
        }
    }

readJsonFile()方法 ---- 获取JSON文件数据并将其JSON数据转换为字符串

//读取Json文件为字符串 String jsonStr = readJsonFile(filePath);
    public static String readJsonFile(String fileName) {
        String jsonStr = "";
        File jsonFile;
        FileReader fileReader = null;
        Reader reader = null;
        StringBuffer sb;
        try {
            jsonFile = new File(fileName);
            fileReader = new FileReader(jsonFile);
            reader = new InputStreamReader(new FileInputStream(jsonFile), "utf-8");
            int ch = 0;
            sb = new StringBuffer();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            jsonStr = sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileReader.close();
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return jsonStr;
    }

showPlayers()方法 ---- 将players JSON字符串信息整理并返回

//输出players信息
    public static String showPlayers(String jsonStr) {
        //将Json字符串通过fastjson转为JSONObject对象
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        JSONArray players = JSONArray.parseArray(jsonObject.getString("players"));
        StringBuffer sb = new StringBuffer();
        String full_name = null; //选手全名
        String gender = null; //选手性别
        String nationality = null; //国籍
        for (int i = 0; i < players.size(); i++) {
            JSONObject player = players.getJSONObject(i);
            full_name = player.getString("full_name");
            gender = player.getString("gender");
            nationality = player.getJSONObject("nationality").getString("name");
            sb.append("full_name:" + full_name + "\n");
            sb.append("gender:" + (gender.equals("M") ? "male" : "female") + "\n");
            sb.append("nationality:" + nationality + "\n");
            sb.append("-----\n");
        }
        return sb.toString(); //返回整理后的字符串
    }

getInput()方法 ---- 获取输入指令

//获取输入指令 String input = getInput(filePath);
    public static List<String> getInput(String fileName) throws Exception {
        File file = new File(fileName);

        //若输入文件不存在则报错
        if (!file.exists()) {
            throw new Exception("输入文件不存在");
        }

        FileReader reader;
        BufferedReader bufferedReader = null;
        StringBuffer sb;
        String str = null;
        List<String> list = new ArrayList<>();
        try {
            file = new File(fileName);
            reader = new FileReader(file);
            bufferedReader = new BufferedReader(reader);
            sb = new StringBuffer();
            String s = "";
            while ((s = bufferedReader.readLine()) != null) {
                list.add(s); //指令字符串列表
                sb.append(s + "\n");
            }
            str = sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

setOutput()方法 ---- 将整理的数据写入文件

//进行输出 String output = setOutput(fileName, data);
    public static void setOutput(String fileName, String data) {
        File file = new File(fileName);

        //若文件不存在则创建文件
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        Writer writer = null;
        StringBuilder outputStr = new StringBuilder();
        try {
            outputStr.append(data); //结尾不换行
            writer = new FileWriter(file, true); //追加
            writer.write(outputStr.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

性能改进

使用缓存机制优化文件读写

在这里插入图片描述
在这里插入图片描述
通过将指令所对应的JSON数据存入缓存中可以减少JSON数据的读取时间

在这里插入图片描述
在这里插入图片描述

单元测试

测试命令行指令格式正误判断、input.txt文件中指令正误判断、对比输出结果是否正确

在这里插入图片描述
提高覆盖率要尽可能覆盖到程序中不同的分支结构,Lib类中有一些处理流异常的指令无法覆盖到,所以Lib类的覆盖率会相对低一点

异常处理

在这里插入图片描述
在这里插入图片描述

心得体会

通过这次的作业,我学会了如何使用Java去解析JSON数据。因为以前处理的JSON数据都是比较简洁比较好整理的,所以看到作业复杂的JSON数据感觉很乱,理不清数据的联系。后面通过请教同学,自己慢慢搞懂的数据的结构和逻辑,写起代码就变得容易一些了。

​刚开始本来是使用Gson解析JSON,但后面发现使用FastJSON会方便一些,又把用Gson的地方改成FastJSON,但修改类库时报了很多错误,后面发现使用maven构建项目只需导入坐标即可,不用去下载jar包,又改成了maven的形式。测试的时候本来是使用JUnit4,但发现很多教程中的方法都是使用JUnit5,JUnit4和JUnit5使用起来有点区别,后面又改成了使用JUnit5。总之,一开始就得规划好要使用的工具,不然后面要改动代码的话就会牵一发而动全身。

​总结,还是得不断学习,拓展自己的技术栈,这样遇到问题时才能更加得心应手。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
摘 要 伴随着人才教学的关注度越来越高,对于人才的培养也是当今社会发展的最为重要的问题之一。为了进一步的进行人才的培养关工作,许多的学校或者是教育的机构逐步的开展了网络信息化的教学和和管理工作,通过信息化的手段和技术实现网络信息化的教育及管理模式,通过网络信息化的手段实现在线答题在线考试和学生信息在线的管理等操作。这样更加的快捷解决了人才培养之中的问题,也在进一步的促进了网络信息化教学方式的快速的发展工作。相较于之前的人才教育和培养工作之中,存在这许多的问题和局限性。在学生信息管理方面通过线下管理的形式进行学生信息的管理工作,在此过程之中存在着一定的局限性和低效性,往往一些突发的问题导致其中工作出现错误。导致相关的教育工作受到了一定的阻碍。在学生信息和学生成绩的管理方面,往常的教育模式之下都是采用的是人工线下的进行管理和整理工作,在这一过程之中存在这一定的不安全和低效性,面对与学生基数的越来越大,学生的信息管理也在面领着巨大的挑战,管理人员面领着巨大的学生信息的信息量,运用之前的信息管理方式往往会在统计和登记上出现错误的情况的产生,为后续的管理工作造成了一定的困难。然而通过信息化的管理方式进行对学生信息的管理不仅可以避免这些错误情况的产生还可以进一步的简化学生信息管理工作的流程,节约了大量的人力和物力的之处。在线答题系统的实现不仅给学生的信息管理工作和在线考试带来了方便也进一步的促进了教育事业信息化的发展,从而实现高效化的教学工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值