139
社区成员
这个作业属于哪个课程 | 2022年福大-软件工程、实践-W班 |
---|---|
这个作业要求在哪里 | 软件工程实践第二次作业——个人实战 |
这个作业的目标 | 完成对冬奥会的赛事数据的收集,并实现一个能够对国家排名及奖牌个数统计的控制台程序 |
其他参考文献 | 百度 |
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 23 |
• Estimate | • 估计这个任务需要多少时间 | 20 | 23 |
Development | 开发 | 985 | 1180 |
• Analysis | • 需求分析 (包括学习新技术) | 40 | 100 |
• Design Spec | • 生成设计文档 | 30 | 20 |
• Design Review | • 设计复审 | 10 | 10 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 15 | 20 |
• Design | • 具体设计 | 60 | 70 |
• Coding | • 具体编码 | 600 | 470 |
• Code Review | • 代码复审 | 30 | 70 |
• Test | • 测试(自我测试,修改代码,提交修改) | 200 | 420 |
Reporting | 报告 | 80 | 115 |
• Test Report | • 测试报告 | 30 | 30 |
• Size Measurement | • 计算工作量 | 20 | 35 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 30 | 50 |
合计 | 1085 | 1318 |
进入冬奥官网 选择赛程,按键F12并刷新出现上图所示,点击网络,选择所需要的数据在新标签页打开,下载到本地data文件夹,这样更方便对于数据的读取和处理
保存下来后,用vscode对文件格式化,对头尾进行处理,再用在线网站进行unicode中文转换,将转换后数据中的 " % / "全部替换为" / "
使用BuilderReader.readLine()和BuilderWriter对文件进行读写,使用StringBuilder.append()将读取到的文件内容拼接
引入第三方库Gson,根据data文件夹中json数据的特点,因BufferReader.readLine()可读取一行的信息,所以当读取到" }," 或者 " }" 时,就可以用gson提取一个对象
Matches match = gson.fromJson(builder.toString(), Matches.class);
共有四个类:OlympicSearch、Lib、Medals、Matches。
OlympicSearch类
public class OlympicSearch
{
//br用于读input.txt文件,bw用于写output.txt文件
BufferedReader br;
BufferedWriter bw;
//根据传入的路径初始化 br和 bw
public OlympicSearch(String input,String output)
//获取 br
public BufferedReader getBufferReader()
//获取 bw
public BufferedWriter getBufferWriter()
//判断日期是否正确,传入的参数为用空格分割指令得到的字符串数组
public static boolean rightDate(String[] strs)
public static void main(String[] args)
}
Lib类
public class Lib
{
//用于存储对应输出结果的字符串,以便重复指令可直接输出该字符串,提高性能
String medalsString;
Map<String,String> matchesString;
BufferedWriter bw;
//获取OlympicSearch的属性bw
Lib(BufferedWriter bw)
//读取date.json文件,将该日期下输出结果的字符串存储在matchesString中
void initMatches(String date) throws IOException
//读取total.json文件,将输出结果的字符串存储在medalsString中
void initMeadls() throws IOException
//main方法中在指令正确情况下调用该函数
void printMedals() throws IOException
//main方法中在指令正确情况下调用该函数
void printMatches(String date) throws IOException
}
Medals类(用于Gson匹配json数据)
class Medals
{
String rank;
String countryid;
String gold;
String silver;
String bronze;
String count;
//对得到的json数据进行处理
public void changeData()
//转换成字符串
public String toString()
}
Matches类(用于Gson匹配json数据)
class Matches
{
String startdatecn;
String itemcodename;
String title;
String homename, awayname;
String venuename;
//对得到的json数据进行处理
public void changeData()
//转换成字符串
public String toString()
}
当输入指令为 schedule 0202 时,main函数会调用 Lib.printMatches("0202") 方法
void printMatches(String date) throws IOException
{
if(!matchesString.containsKey(date))
{
try
{
initMatches(date);
}
catch (IOException e)
{
System.out.println("读取"+date+".json文件失败");
}
}
bw.write(matchesString.get(date));
bw.flush();
}
此处用到Gson并不是直接对整个json数组解析 ,而是通过 StringBuilder 和 BufferedReader 将json文件划分成一个个对象,转换为一个个Matches类,逐个存储到 List<Matches> matchesList中,最后用for循环将matchesList中的每个Matches通过调用 Matches.toString() 方法得到的字符串拼接在一起,赋值给 matchesString
void initMatches(String date) throws IOException
{
Gson gson = new Gson();
String content = "";
List<Matches> matchesList=new ArrayList<Matches>();
StringBuilder builder = new StringBuilder();
String filePath = "src\\data\\schedule\\" + date + ".json";
File file = new File(filePath);
if (!file.exists()) System.out.println("找不到文件"+date+".json");
InputStreamReader streamReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
BufferedReader bufferedReader = new BufferedReader(streamReader);
//对读取到的json数据划分成单个对象的字符串,再用gson转化成match类
while ((content = bufferedReader.readLine()) != null)
{
if (content.equals(" },") || content.equals(" }"))//根据”...“划分
{
builder.append(" }");
Matches match = gson.fromJson(builder.toString(), Matches.class);
match.changeData();
matchesList.add(match);
builder.delete(0, builder.length());//每提取完一个match类,对builder读取到的内容清空
if (content.equals(" }")) break;
} else builder.append(content);
if (content.equals(" \"matchList\": [")) builder.delete(0, builder.length());//将无效内容删除
}
//将所需的输出内容存储到Map<String,String> matchesString中
builder.delete(0, builder.length());
for (int i=0;i<matchesList.size();i++)
{
builder.append(matchesList.get(i).toString());
if(i<matchesList.size()-1) builder.append("\n");
}
matchesString.put(date,builder.toString());
bufferedReader.close();
streamReader.close();
}
当输入指令为total时,main函数调用Lib.printMedals()方法
相关部分代码与输入指令为 schedule 0202相似,就不再细说
main函数流程图
用包含3000条指令的input.txt测试代码运行情况:
改进前:
改进后:
性能分析
改进前:
改进后:
以下为部分单元测试代码
@Test
public void testrightDate()
{
search=new OlympicSearch("E:\\软件工程\\OlympicSearch\\input.txt","E:\\软件工程\\OlympicSearch\\output.txt");
lib=new Lib(search.getBufferWriter());
try
{
lib.printMedals();
lib.initMatches("0202");
lib.printMatches("");
lib.initMatches("0201");
}
catch (IOException e)
{
e.printStackTrace();
}
}
@Test
public void testrightDate()
{
assertEquals(true,OlympicSearch.rightDate(new String[]{"schedule","0202"}));
assertEquals(true,OlympicSearch.rightDate(new String[]{"schedule","0220"}));
assertEquals(true,OlympicSearch.rightDate(new String[]{"schedule","0213"}));
assertEquals(true,OlympicSearch.rightDate(new String[]{"schedule"," ","0202"}));
assertEquals(false,OlympicSearch.rightDate(new String[]{"schedule","大时代"}));
assertEquals(false,OlympicSearch.rightDate(new String[]{"schedule","asadsa"}));
}
public void testOlympic()
{
OlympicSearch search1=new OlympicSearch("E:\\软件工程\\OlympicSearch\\input.txt","E:\\软件工程\\OlympicSearch\\output.txt");
OlympicSearch search2=new OlympicSearch("E:\\软件工程\\OlympicSearch\\i1.txt","E:\\软件工程\\OlympicSearch\\t.txt");
}
void initMeadls() throws IOException
File file = new File("src\\data\\total.json");
if (!file.exists()) System.out.println("找不到文件total.json");
public OlympicSearch(String input,String output)
{
try
{
InputStream in=new FileInputStream(input);
OutputStream out=new FileOutputStream(output);
br=new BufferedReader(new InputStreamReader(in,"UTF-8"));
bw=new BufferedWriter(new OutputStreamWriter(out,"UTF-8"));
}
catch(FileNotFoundException e)
{
System.out.println("文件找不到");
}
catch (UnsupportedEncodingException e)
{
System.out.println("转码异常");
}
}