寒假作业(2/2)
这个作业属于哪个课程 | 2020春|S班(福州大学) |
---|---|
这个作业的要求在哪里 | 寒假作业(2/2) |
这个作业的目标 | |
作业正文 | .... |
其他参考文献 | CSDN、知乎、百度等相关问题 |
1、Github仓库地址
fzu-hushixin
2、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
Estimate | 估计这个任务需要多少时间 | 30 | 30 |
Development | 开发 | 630 | 690 |
Analysis | 需求分析 (包括学习新技术) | 60 | 60 |
Design Spec | 生成设计文档 | 60 | 60 |
Design Review | 设计复审 | 30 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 30 |
Design | 具体设计 | 60 | 60 |
Coding | 具体编码 | 300 | 360 |
Code Review | 代码复审 | 60 | 60 |
Test | 测试(自我测试,修改代码,提交修改) | 30 | 30 |
Reporting | 报告 | 80 | 80 |
Test Repor | 测试报告 | 30 | 30 |
Size Measurement | 计算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 740 | 800 |
3、解题思路
3.1、解题思路描述
- 创建一个province类数组,按顺序存储各省的名字,并且将各种疫情感染情况初始化为0,同时编写set与get方法来修改和读取变量。
- 读取命令行参数,Java中命令行参数是保存于args字符串数组中的,将args数组根据题目具体要求进行遍历查找,实现相应功能。
- 根据不同的命令行参数的要求,读取相应的日志文件,并且将日志文件内容中具体的疫情感染情况按省名存储于province类数组中。
- 根据命令行,按要求将province类数组存储的内容输出到output.txt文件中。
3.2、命令行参数具体分析
list命令 支持以下命令行参数:
- -log 指定日志目录的位置,该项必会附带,请直接使用传入的路径,而不是自己设置路径
- -out 指定输出文件路径和文件名,该项必会附带,请直接使用传入的路径,而不是自己设置路径
- -date 指定日期,不设置则默认为所提供日志最新的一天。你需要确保你处理了指定日期以及之前的所有log文件
- -type 可选择[ip: infection patients 感染患者,sp: suspected patients 疑似患者,cure:治愈 ,dead:死亡患者],使用缩写选择,如 -type ip 表示只列出感染患者的情况,-type sp cure则会按顺序【sp, cure】列出疑似患者和治愈患者的情况,不指定该项默认会列出所有情况。
- -province 指定列出的省,如-province 福建,则只列出福建,-province 全国 浙江则只会列出全国、浙江
注:java InfectStatistic表示执行主类InfectStatistic,list为命令,-date代表该命令附带的参数,-date后边跟着具体的参数值,如2020-01-22。-type 的多个参数值会用空格分离,每个命令参数都在上方给出了描述,每个命令都会携带一到多个命令参数
因此,首先要分析命令行参数是否带-log与-out,如果不带则直接返回错误,否侧记录下后面的路径。同时,判断命令行是否带有-date、-type、-province,对于每一种情况有不同的处理方式。
3.3、复习java基本内容
通过百度、CSDN、博客园等途径,回顾了java处理文件流的方法,同时回顾了String的一些方法,为程序的完成打下了基础。
4、设计实现过程
4.1、代码组织
4.2、关键函数流程图
5、代码说明
5.1、初始化province类数组
province类数组的初始化,保证在将数据输出到output.txt中时,各省按拼音排序
String[] province_name = new String[] {"全国","安徽","北京","重庆","福建","甘肃","广东","广西",
"贵州","海南","河北","河南","黑龙江","湖北","湖南","吉林","江苏","江西","辽宁","内蒙古",
"宁夏","青海","山东","山西","陕西","上海","四川","天津","西藏","新疆","云南","浙江"};
province[] pro;
pro = new province[province_name.length];
in.init_province(pro , province_name); //将参数传入函数
public void init_province(province[] pro , String[] str) //初始化函数
{
for(int i = 0 ;i < str.length ;i++)
{
pro[i] = new province();
pro[i].set_pro_name(str[i]);
}
}
5.2、命令行处理分析
通过遍历命令行数组,查询是否存在-log、-out等等选项,对于不同的选项有不同的处理方式
public void process_command(String[] args , province[] pro) throws IOException // 处理命令行参数
{
if(!args[0].equals("list")) //判断命令行是否存在
{
System.err.println("输入命令错误");
return;
}
boolean if_log = false;
boolean if_out = false;
boolean if_date = false;
boolean if_type = false;
boolean if_province = false;
String[] path = new String [2];
String date = new String();
String[] type = new String [args.length];
String[] out_pro = new String[args.length];
for(int i = 1 ; i < args.length ; i++)
{
if(args[i].equals("-log"))
{
if_log = true;
path[0] = new String(args[i+1]);
}
if(args[i].equals("-out"))
{
if_out = true;
path[1] = new String(args[i+1]);
}
if(args[i].equals("-date"))
{
if_date = true;
date = args[i+1];
}
if(args[i].equals("-type"))
{
if_type = true;
for(int x = i+1 ; x < args.length ; x++)
{
type[x-i-1] = args[x];
}
}
if(args[i].equals("-province"))
{
if_province = true;
for(int x = i+1 ; x < args.length ; x++)
{
out_pro[x-i-1] = args[x];
}
}
}
if(!if_log || !if_out) //如果不存在-out或者-log则报错返回
{
System.err.println("输入命令错误");
return;
}
if(!if_date) //如果不存在-date,则设置date为最新一天
{
Date dd = new Date();
SimpleDateFormat sim = new SimpleDateFormat("yyyy-MM-dd");
date = sim.format(dd);
}
String[] file_name;
file_name = this.read_log_name(path[0] , date); //读取路径下符合规定的文件名
for(int i = 0 ; i < file_name.length ; i++)
{
if(file_name[i] != null)
{
this.process_log(path[0] , file_name[i] , pro); //根据文件名处理日志
}
}
this.process_country(pro); //根据province类数组中其他省的情况统计全国情况
if(if_type && !if_province )
{
this.output_type(path[1] , pro , type);
}
else if(if_province && !if_type)
{
this.output_pro(path[1] , pro , out_pro);
}
else if(if_province && if_type)
{
this.output_pro_type(path[1] , pro , out_pro , type);
}
else
{
this.output(path[1], pro);
}
}
5.3、日志处理
根据日志文件名打开相应的日志文件,同时对每一行日志文件信息进行提取数据并将数据存入province类数组中
public void process_log(String pa,String log_name , province[] pro) throws IOException //读取日志并统计日志内疫情情况
{
String result = new String (pa+"\\"+log_name);
FileInputStream fstream = new FileInputStream(new File(result));
BufferedReader br = new BufferedReader(new InputStreamReader(fstream,"UTF-8"));
String strLine;
while((strLine = br.readLine()) != null)
{
this.process_string(strLine , pro); // 处理日志中每一行的疫情统计情况
}
br.close();
}
5.4、输出处理
对于不带-province、-type的命令
public void output(String pa,province[] pro) throws IOException // 将统计结果输出到output.txt
{
String path = new String(pa); //创建对应名字的输出文件
FileWriter fwriter = new FileWriter(path);
for(int i = 0 ; i < pro.length ; i++)
{
String word = new String();
if(pro[i].get_cure() != 0 || pro[i].get_death() != 0 || pro[i].get_infected() != 0 || pro[i].get_suspected() != 0)
{
word += pro[i].get_pro_name() + " 感染患者" + pro[i].get_infected() + " 疑似患者" +
pro[i].get_suspected() + " 治愈" + pro[i].get_cure() + " 死亡" + pro[i].get_death() + "\n";
fwriter.write(word);
word = "";
}
}
fwriter.flush();
fwriter.close();
}
注:对于带有不同的命令参数的输出日志,只需要在此基础上进行修改。例如带-province命令,则只需要遍历将特定的省的情况输出到日志即可(-type)类似
6、单元测试截图和描述
- 命令:list -log D:\log -out D:\ListOut1.txt -date 2020-01-22
- 命令:list -log D:\log -out D:\ListOut2.txt -date 2020-01-22 -province 福建 河北
- 命令:list -log D:\log -out D:\ListOut3.txt -date 2020-01-23 -type cure dead ip -province 全国 浙江 福建
- 命令:list -log D:\log -out D:\ListOut4.txt -date 2020-01-23 -type cure
- 命令:list -log D:\log -out D:\ListOut5.txt -date 2020-01-23 -type dead
- 命令:list -log D:\log -out D:\ListOut6.txt -date 2020-01-23 -type ip
- 命令:list -log D:\log -out D:\ListOut7.txt -date 2020-01-23 -type sp
- 命令:list -log D:\log -out D:\ListOut8.txt -date 2020-01-23 -type dead -province 福建
- 命令:list -log D:\log -out D:\ListOut9.txt -date 2020-01-25 -type dead -province 福建
- 命令:list -log D:\log -out D:\ListOut10.txt -date 2020-01-01 -type dead -province 福建
7、单元测试覆盖率优化和性能测试
第一次进行单元测试时发现一个函数内的错误:
进行调试发现在转化时忘记添加对字符'0'的处理,修改了代码,最后测试结果正确:
由于本人没有使用IDEA,所以对性能测试不是很严格,只是简单的查看了内存和CPU的利用率
8、git仓库链接
代码规范链接
9、心路历程和收获
心路历程:
本次作业刚开始拿到时心里还是很忐忑,因为涉及到Github的学习使用、命令行的处理这些新内容的学习。为此,自己还花了不少时间在这上面,因为Github的网站是全英文的,自己的英语基础不是很好,使用起来很困难。通过知乎、CSDN等平台上查了不少的资料后,勉强弄懂了Github的使用,在同学的帮助下,自己也是明白了命令行应该如何去处理。总的来说,本次实践能够完成自己还是花了较多的时间。
收获:
这次实践我充分意识到自己平时应该多注重基础的扎实,因为完成程序的过程中,很多以前学过的包括文件流的处理,字符串的方法等等内容都已经忘记,完全靠百度查资料,这是很不好的。同时,也让我意识到不论是现在还是以后,自己动手查资料的习惯要养成,要善于去自己学习使用新的软件,并且要有自学能力,对于新知识要多花时间去理解。
10、技术路线图相关的5个仓库
- java后端
仓库内含有基础的java内容,包括:数据结构、常用算法、书籍、数据库基础 MySQL等等有关后端的知识
- 微信小程序Java后端Demo
本项目为WxJava的Demo演示程序,基于Spring Boot构建,实现微信小程序后端开发功能,支持多个小程序。
- Java仿微信全栈 高性能后台+移动客户端
Java仿微信全栈 高性能后台+移动客户端,含有Backend 项目后端代码、Fronkend 项目前端代码等等
- Java Web工程demo 后端
spring + spring mvc + mybatis + maven,涉及定时任务quartz、ehcache缓存、RESTful API、邮件发送... 前端:react + reflux + webpack,涉及ES6、jquery、react-router、ant design等内容,提供思路
- java个人博客
java搭建个人博客,完成的后台,和大气的前端页面