软工实践寒假作业(2/2)

这个作业属于哪个课程 2020春|S班 (福州大学)
这个作业要求在哪里 寒假作业(2/2)
这个作业的目标 开发一个疫情统计程序
作业正文 软工实践寒假作业(2/2)
其他参考文献 Github

Github仓库地址

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 10 20
Estimate 估计这个任务需要多少时间 5 5
Development 开发 300 180
Analysis 需求分析 (包括学习新技术) 120 240
Design Spec 生成设计文档 30 50
Design Review 设计复审 10 60
Coding Standard 代码规范 (为目前的开发制定合适的规范) 30 30
Design 具体设计 30 30
Coding 具体编码 30 30
Code Review 代码复审 30 60
Test 测试(自我测试,修改代码,提交修改) 60 60
Reporting 报告 30 60
Test Repor 测试报告 30 10
Size Measurement 计算工作量 10 5
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30 20
合计 755 850

解题思路描述

阅读题目 理解题目
发现java的知识忘得差不多了 先去网上查了点cmd运行java的资料 理解题目中的“命令”“命令行参数”“参数”是什么意思
理解题目的需求 是对信息按规定要求的整理
仔细理解每个要求的具体内容 保证不出错
每个信息有他的子信息 首先想到构造结构体(java中是类的实例) 把单个省份的情况封装起来进行操作
读取用字符串数组“命令”“命令行参数”“参数” 并按各个参数产生分支 再处理各个分支的具体工作
发现文件中有几种固定的格式并用空格分开 想到用空格分割字符串 再按格式中关键字的前后文读出具体的信息

实现过程

代码说明

读取参数

public static void readParameter(String args[]) {
    	for(int i = 0;i<args.length;i++) {
    		if(args[i].equals("-log"))
        	path = args[i+1];
        	if(args[i].equals("-out"))
        	out = args[i+1];
        	if(args[i].equals("-date"))
            date = args[i+1];
        	if(args[i].equals("-type")) {
        		i++;
        		while(i < args.length&&args[i].charAt(0) != '-') {
        			type.add(args[i]);
        			i++;
        		}
        		i--;
        	}
        	if(args[i].equals("-province")) {
        		i++;
        		while(i < args.length&&args[i].charAt(0) != '-') {
        			province.add(args[i]);
        			i++;
        		}
        		i--;
        	}
    	}
	}

读取-path目录下的文件 在读取完-date参数对应的文件后退出 用信息中的关键字判断读入的方式

public static void readFile(File[] tempList) throws NumberFormatException, IOException {
        if(!date.equals("")) {
    		if(tempList[tempList.length-1].getName().toString().substring(0,10).compareTo(date)<0) {
        		System.out.print("日期超出范围!");
        		System.exit(0);
        	}
    	}
    	for(int i=0;i<tempList.length;i++) {    		
    		if(tempList[i].isFile()) {
    			if(!date.equals("")) { 			
    				if(tempList[i].getName().toString().substring(0,10).compareTo(date)>0) {
    					break;		
    				}
        		}
    			BufferedReader br = new BufferedReader(  
    				     new UnicodeReader(  
    				     new FileInputStream(tempList[i]),   
    				     "UTF-8")); 
    			InputStreamReader read = new InputStreamReader(new FileInputStream(tempList[i]), "UTF-8");
                BufferedReader reader = new BufferedReader(read);
    			String str;     			
    			while ((str = br.readLine())!= null) {
    				String[] arrays = str.split("\s+");
    				for(int j = 0;j<arrays.length;j++) {
    					Info t = new Info();					
    					switch(arrays[j]) {
    						 case "新增":
    							 t.province=arrays[j-1];							 
    							 if(list.contains(t)) {
    								 if(arrays[j+1].equals("感染患者")) {
    									 list.get(list.indexOf(t)).infected+=Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
    									 all.infected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
    								 }
    								 else {
    									 list.get(list.indexOf(t)).suspected+=Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
    									 all.suspected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
    								 } 								 
    							 }
    							 else {
    								 if(arrays[j+1].equals("感染患者")) {
    									 t.infected = Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));  
    									 all.infected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
    								 }
    								 else {
    									 t.suspected = Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));  
    									 all.suspected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
    								 }  
    								 
    								 list.add(t);
    							 }
    				            break;
    				         case "流入":
    				        	 Info from = new Info();
    				        	 Info to = new Info();
    				        	 from.province = arrays[j-2];
    				        	 to.province = arrays[j+1];
    							 if(list.contains(to)) {
    								 if(arrays[j-1].equals("感染患者")) {
    									 list.get(list.indexOf(from)).infected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
    									 list.get(list.indexOf(to)).infected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1)); 
    								 }
    								 else {
    									 list.get(list.indexOf(from)).suspected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
    									 list.get(list.indexOf(to)).suspected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));  
    								 }     								 
    							 }
    							 else {
    								 if(arrays[j-1].equals("感染患者")) {
    									 list.get(list.indexOf(from)).infected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
    									 to.infected = Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));  
    								 }
    								 else {
    									 list.get(list.indexOf(from)).suspected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
    									 to.suspected = Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));  
    								 }   								 
    								 list.add(to);
    							 }
    				            break;
    				         case "死亡":
    							 t.province = arrays[j-1];
    							 list.get(list.indexOf(t)).infected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
    							 list.get(list.indexOf(t)).dead += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
    							 all.infected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
    							 all.dead += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
    				            break;
    				         case "治愈":
    				        	 t.province = arrays[j-1];
    				        	 list.get(list.indexOf(t)).infected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
    							 list.get(list.indexOf(t)).cured += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
    							 all.infected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
    							 all.cured += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
    				            break;
    				         case "确诊感染":
    				        	 t.province = arrays[j-2];
    				        	 list.get(list.indexOf(t)).suspected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
    							 list.get(list.indexOf(t)).infected += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1));   
    							 all.suspected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
    							 all.infected += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
     				            break;
    				         case "排除":
    				        	 t.province = arrays[j-1];
    				        	 list.get(list.indexOf(t)).suspected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1)); 
    				        	 all.suspected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1)); 
     				            break;
    				         default:
    				            break;
    					}
    				}
    			}  			
    			reader.close();
    			br.close();
    		}
    		
    		
    	}     	
    	Collections.sort(list, new Comparator<Info>() {
			@Override
			public int compare(Info o1, Info o2) {
				// TODO Auto-generated method stub
				Comparator<Object> com = Collator.getInstance(java.util.Locale.CHINA);  
				 return com.compare(o1.province, o2.province); 
			}
        });
	}

输出到命令行检查 写入-out路径的文件 根据-province和-type的有无判断输出和写入方式

public static void out() throws IOException {
    	FileWriter fw = new FileWriter(out);
		BufferedWriter fout = new BufferedWriter(fw);
    	if(province.size()>0) {
    		if(province.contains("全国")) {
    			printTypeInfo(all, type,fout);	
    		}
			if(type.size()>0) {
				for(int k = 0;k<province.size();k++) {
					Info t = new Info();
					t.province = province.get(k);
    				if(list.contains(t)) {
    					printTypeInfo(list.get(list.indexOf(t)), type, fout);
    				}
    				else {
    					printTypeInfo(t, type, fout);
    				}
    			}
			}
			else {
				for(int k = 0;k<province.size();k++) {
					Info t = new Info();
					t.province = province.get(k);
    				if(list.contains(t)) {
    					printInfo(list.get(list.indexOf(t)), fout);
    				}
    				else {
    					printInfo(t, fout);
    				}
    			}
			}
		}
		else {
			if(type.size()>0) {
				for(int k = 0;k<list.size();k++) {
					printTypeInfo(list.get(k), type, fout);
    			}
			}
			else {
				printInfo(all,fout);
				for(int k = 0;k < list.size();k++) {
					printInfo(list.get(k),fout);	
    			}
			}
			
		}
    	fout.close();
	}

无法确定读入的文件的编码方式 统一在读取时去除BOM防止意外的字符

class UnicodeReader extends Reader {   //工具类用于读取文件去除BOM
	  PushbackInputStream internalIn;  
	  InputStreamReader internalIn2 = null;  
	  String defaultEnc;  
	  
	  private static final int BOM_SIZE = 4;   
	  UnicodeReader(InputStream in, String defaultEnc) {  
	     internalIn = new PushbackInputStream(in, BOM_SIZE);  
	     this.defaultEnc = defaultEnc;  
	  }  
	  
	  public String getDefaultEncoding() {  
	     return defaultEnc;  
	  }      
	  public String getEncoding() {  
	     if (internalIn2 == null) return null;  
	     return internalIn2.getEncoding();  
	  }      
	  protected void init() throws IOException {  
	     if (internalIn2!=null) return;  	  
	     String encoding;  
	     byte bom[] = new byte[BOM_SIZE];  
	     int n,unread;  
	     n = internalIn.read(bom, 0, bom.length);  
	  
	     if ( (bom[0] == (byte)0x00) && (bom[1] == (byte)0x00) &&  
	                 (bom[2] == (byte)0xFE) && (bom[3] == (byte)0xFF) ) {  
	        encoding = "UTF-32BE";  
	        unread = n-4;  
	     } else if ( (bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) &&  
	                 (bom[2] == (byte)0x00) && (bom[3] == (byte)0x00) ) {  
	        encoding = "UTF-32LE";  
	        unread = n-4;  
	     } else if (  (bom[0] == (byte)0xEF) && (bom[1] == (byte)0xBB) &&  
	           (bom[2] == (byte)0xBF) ) {  
	        encoding = "UTF-8";  
	        unread = n-3;  
	     } else if ((bom[0] == (byte)0xFE) && (bom[1] == (byte)0xFF)) {  
	        encoding = "UTF-16BE";  
	        unread = n-2;  
	     } else if ((bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE)) {  
	        encoding = "UTF-16LE";  
	        unread = n-2;  
	     } else {  
	        // Unicode BOM mark not found, unread all bytes  
	        encoding = defaultEnc;  
	        unread = n;  
	     }      
	     //System.out.println("read=" + n + ", unread=" + unread);  
	  
	     if (unread>0)
	    	 internalIn.unread(bom,(n-unread),unread);  
	  
	     // Use given encoding  
	     if (encoding == null) {  
	        internalIn2 = new InputStreamReader(internalIn);  
	     } else {  
	        internalIn2 = new InputStreamReader(internalIn, encoding);  
	     }  
	  }  
          public void close() throws IOException {  
	     init();  
	     internalIn2.close();  
	  }  
	  
	  public int read(char[] cbuf,int off,int len) throws IOException {  
	     init();  
	     return internalIn2.read(cbuf, off, len);  
	  }  
	  
}  

存放信息使用的类

class Info implements Comparable<Info>{
	String province;
	int infected = 0;
	int suspected = 0;
	int dead = 0;
	int cured = 0;
	@Override
	public int compareTo(Info o) {
		// TODO Auto-generated method stub
		Comparator<Object> com = Collator.getInstance(java.util.Locale.CHINA);  
		 return com.compare(this.province, o.province); 
	}
	public boolean equals(Object o) {
		Info t = (Info)o;
		return this.province.equals(t.province);
	}
}

单元测试

log内容

测试1

@Test
void test1() throws FileNotFoundException, IOException { //无参数情况
	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output1.txt"};
	InfectStatistic.main(args);
}

结果

测试2

@Test
void test2() throws FileNotFoundException, IOException { //省份参数无记录情况
	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output2.txt","-province","湖南"};
	InfectStatistic.main(args);
}

结果

测试3

@Test
void test3() throws FileNotFoundException, IOException { //带日期参数
	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output3.txt","-date", "2020-01-21"};
	InfectStatistic.main(args);
}

结果

测试4

@Test
void test4() throws FileNotFoundException, IOException { //带类型参数
	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output4.txt","-type","cure"};
	InfectStatistic.main(args);
}

结果

测试5

@Test
void test5() throws FileNotFoundException, IOException { //带多个省份参数
	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output5.txt","-province","福建","全国"};
	InfectStatistic.main(args);
}

结果

测试6

@Test
void test6() throws FileNotFoundException, IOException { //同时带日期和类型参数
	String args[]= {"list", "-date", "2020-01-25", "-log", "D:/log/", "-out", "D:/output6.txt","-type","cure"};
	InfectStatistic.main(args);
}

结果

测试7

@Test
void test7() throws FileNotFoundException, IOException { //同时带日期和省份参数
	String args[]= {"list", "-date", "2020-01-22", "-log", "D:/log/", "-out", "D:/output7.txt","-province","福建"};
	InfectStatistic.main(args);
}

结果

测试8

@Test
void test8() throws FileNotFoundException, IOException { //同时带日期、无记录省份、类型参数
	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output8.txt","-type","cure","-province","福建","江苏"};
	InfectStatistic.main(args);
}

结果

测试9

@Test
void test9() throws FileNotFoundException, IOException { //同时带日期省份类型参数
	String args[]= {"list", "-date", "2020-01-22", "-log", "D:/log/", "-out", "D:/output9.txt","-type","sp","-province","福建"};
	InfectStatistic.main(args);
}

结果

测试10

@Test
void test10() throws FileNotFoundException, IOException { //同时带日期多个类型多个省份参数
	String args[]= {"list", "-date", "2020-01-22", "-log", "D:/log/", "-out", "D:/output10.txt","-type","ip","dead","-province","福建","全国"};
	InfectStatistic.main(args);
}

结果

单元测试覆盖率及性能优化

单元测试覆盖率
在范例给的log基础上添加了其他的情况 增加覆盖率

性能测试

代码规范

codstyle.md

心路历程与收获

《构建之法》中提到:关于工程师与程序员的区别是关于代码的规范程度。没读这本书之前,并不太懂软件工程的概念,只是认为软件的核心的就是代码,那么软件工程的核心就是写代码的程序员如何写好代码。在一开始的读书过程中,我颠覆了以往的观念,但后来其实想想也并无大错,其实软件工程的一系列方法,都是为了让程序员更好的去完成工作。软件这门工程,也如同盖楼一样,一个人的能力强大, 最多让某个结构更加坚固,但是软件工程着眼的是整个工程,并不简简单单局限于某个点某个面。我们所罗列的方法与思想,都是为了整个工程流程而服务的。这才是软件工程的核心所在。这次的作业虽然功能很少,但是还是花了我不少的时间。大多数时间是花在强制自己按规范操作,熟悉规范的软件开发流程。

第一次作业中技术路线图相关的5个仓库

java学习+面试指南
一份涵盖大部分Java程序员所需要掌握的核心知识。帮助复习和巩固java知识,为之后的学习工作打好基础。
HTML,CSS,and JavaScript
最流行的HTML、CSS和JavaScript框架,用于在web上开发响应性强、移动优先的项目。
SSM框架
手把手教你整合最优雅SSM框架:SpringMVC + Spring + MyBatis。
Java后端
从Java基础、JavaWeb基础到常用的框架再到面试题都有完整的教程,几乎涵盖了Java后端必备的知识点。
spring boot demo
是一个用来深度学习并实战 spring boot 的项目。

原文地址:https://www.cnblogs.com/tangcen/p/12327531.html