• Java 使用poi导入excel,结合xml文件进行数据验证的例子(增加了jar包)


    ava 使用poi导入excel,结合xml文件进行数据验证的例子(增加了jar包)

    假设现在要做一个通用的导入方法:

    要求:

    1.xml的只定义数据库表中的column字段,字段类型,是否非空等条件。

    2.excel定义成模板,里面只填写了所需要的数据,有可能数据有问题。

    3.在导入的时候就需要对每个excel单元格的数据进行验证。

    4.验证完之后,若所有数据正确,那么批量保存。若有一点点错误,就不执行保存操作,并提示错误原因。

    思路:

    1.完美使用了Map的功能,先将xml中的数据存入map中,怎么存呢?

    下面我根据xml文件来具体分析:(为图方便,我只做了字段的非空验证)

    user.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <excel>
       <entity name="用户表" code="user" >	
    		<column name="状态" code="status" type="String"></column>	
    		<column name="端口号" code="port" type="int">
    			<rules> 
    				<rule name="nullable" message="端口号不允许为空"></rule>
    			</rules>				
    		</column>	
    	   <column name="IP地址" code="ip" type="String">
    	   	   <rules> 
    				<rule name="nullable" message="IP地址不允许为空"></rule>
    			</rules>	
    	   </column>	 
    	   <column name="密码" code="password" type="String">
    	   	    <rules> 
    				<rule name="nullable" message="密码不允许为空"></rule>
    			</rules>	
    	   </column>   
    	   <column name="用户名" code="username" type="String"></column>   
    	   <column name="员工号" code="no" type="String">	   	
    			<rules>
    				<rule name="nullable" message="员工号不允许为空"></rule>
    				<rule name="checkUnique" message="员工号已经存在"></rule>
    			</rules>	
    	   </column>      
    	   <column name="头像" code="userImage" type="BLOB"></column>  
       </entity>
    </excel>

    根据xml所做的准备:

    准备4个Map:

    (1),已知 <entity> 中的name="用户表" ,定义entityMap 来存放实体类的map对象

    (2),已知 “用户表”和 某个字段名“员工号”,那么就可以存放每一列的map对象

    (3),已知 “用户表”和 某个字段名“员工号”,可以找到该列下的所有验证规则存放到map中

    (4),已知 “用户表” 和 “ 员工号”和验证规则name "nullable",那么可以找到每一列的某一个验证规则

    2.读取excel数据时,需要一一对应xml map中的字段与验证规则。

    下面是excel数据:标注红色 * 号的表示必填项。

    接下来就要看具体的实现代码了:

    东西很多,我只贴两个比较重要的java 类

    1.ParseExcelUtil.java  ,要试验代码,可以直接在工程里面单击右键--run as 运行这个类,不过前提是要导入这个测试项目,最后面我会上传。

    package com.karen.test2;
    
    import java.beans.IntrospectionException;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.hssf.usermodel.HSSFDateUtil;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    
    import com.karen.database.Dao;
    /**
     * 解析excel 工具类
     * @author PCCW
     *
     */
    @SuppressWarnings("rawtypes")
    public class ParseExcelUtil {
    	
    	public  FileInputStream fis ;
    	public HSSFWorkbook workBook;
    	public HSSFSheet sheet;
    	public ParseXMLUtil parseXmlUtil;
    	public StringBuffer errorString;
    	
    	/**当前实体类的code**/
    	public String curEntityCode;
    	/**表头map对象:key:entityCode, value:headMap(index,headTitle)**/
    	public Map curEntityHeadMap ;
    	
    	/**字段的必填:key:entityCode+headTitle, value:true(必填),false(不必填)**/
    	public Map curEntityColRequired;
    	
    	/**存放每一行的数据**/
    	public  List listDatas ;
    	
    	
    	public ParseExcelUtil(File excelFile,File xmlFile){
    		try {
    			if(excelFile == null){
    				throw new FileNotFoundException();
    			}
    		   fis = new FileInputStream(excelFile);		   
    		   workBook = new HSSFWorkbook(fis);
    		   parseXmlUtil = new ParseXMLUtil(xmlFile);
    		   errorString = new StringBuffer();
    		   readExcelData();
    		   	   				
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		}catch (IOException e) {
    			e.printStackTrace();
    		}	
    	}
    	
    	
    	/**开始从excel读取数据**/	
    	public void readExcelData(){
    		int sheetSize = workBook.getNumberOfSheets();
    		for(int i=0;i<sheetSize;i++){
    			sheet = workBook.getSheetAt(i);
    			String entityName = workBook.getSheetName(i);
    			readSheetData(sheet,entityName);
    		}
    		
    	}
    	
    	/**读每个sheet页的数据**/
    	public void readSheetData(HSSFSheet sheet,String entityName){
    		
    		   int rowNumbers = sheet.getPhysicalNumberOfRows();
    		   Map ent = (Map) parseXmlUtil.getEntityMap().get(entityName);
    		   this.setCurEntityCode((String) ent.get("code"));
    		   if(rowNumbers == 0){
    			   System.out.println("================excel中数据为空!");
    			   errorString.append(ParseConstans.ERROR_EXCEL_NULL);
    		   }		  
    			List colList = (List) parseXmlUtil.getColumnListMap().get(entityName);
    			int xmlRowNum = colList.size();
    		   HSSFRow excelRow = sheet.getRow(0);
    		   int excelFirstRow = excelRow.getFirstCellNum();
    		   int excelLastRow = excelRow.getLastCellNum();
    		   if(xmlRowNum  != (excelLastRow-excelFirstRow)){
    			     System.out.println("==================xml列数与excel列数不相符,请检查");
    			     errorString.append(ParseConstans.ERROR_EXCEL_COLUMN_NOT_EQUAL);
    		   }
    		   readSheetHeadData(sheet);
    			   
    		   readSheetColumnData(sheet,entityName);
    		   
    		 
    		 	   
    	   }
    	
       /**读取sheet页中的表头信息**/
       @SuppressWarnings({ "unchecked", "static-access"})
    	public void readSheetHeadData(HSSFSheet sheet){
    	   
    		   Map headMap = new HashMap();
    		   curEntityHeadMap = new HashMap();
    		   curEntityColRequired = new HashMap();
    		   HSSFRow excelheadRow = sheet.getRow(0);
    		   int excelLastRow = excelheadRow.getLastCellNum();
    		   String headTitle = "";
    		   for(int i=0;i<excelLastRow;i++){
    			   HSSFCell cell = excelheadRow.getCell(i);
    			   headTitle = this.getStringCellValue(cell).trim();
    			   if(headTitle.endsWith("*")){
    				   curEntityColRequired.put(this.getCurEntityCode()+"_"+headTitle,true);
    			   }else{
    				   curEntityColRequired.put(this.getCurEntityCode()+"_"+headTitle,false);
    			   }
    			   headMap.put(i, headTitle);
    		   }
    		   curEntityHeadMap.put(this.getCurEntityCode(), headMap);
    	   }
       
       /**读取sheet页里面的数据**/
       @SuppressWarnings({ "unchecked", "static-access" })
    public void readSheetColumnData(HSSFSheet sheet,String entityName){
    	   
    	   HSSFRow excelheadRow = sheet.getRow(0);
    	   int excelLastcell = excelheadRow.getLastCellNum();   //excel总列数
    	   int excelRowNum = sheet.getLastRowNum();  //excel总行数
    	   Map headMap = (Map) this.getCurEntityHeadMap().get(this.getCurEntityCode());	   
    	   Map colMap = parseXmlUtil.getColumnMap();
    	   listDatas =new ArrayList();
    	   
    	   for(int i=1;i<excelRowNum+1;i++){//行循环		  		   
    		   HSSFRow columnRow = sheet.getRow(i);	
    		   if(columnRow != null){
    			   Map curRowCellMap = new HashMap();
    			   for(int j =0; j<excelLastcell;j++){ //列循环
    				   int cout =  headMap.get(j).toString().indexOf("*");
    				   String headTitle ="";
    				   if(cout == -1){
    					  headTitle = headMap.get(j).toString();
    				   }else{
    					   headTitle =  headMap.get(j).toString().substring(0, cout);
    				   }			   		    
    				   Map curColMap =  (Map) colMap.get(entityName+"_"+headTitle);
    				   String curColCode = (String) curColMap.get("code");
    				   String curColType = (String) curColMap.get("type");
    				   HSSFCell colCell = columnRow.getCell(j);
    				   String value =this.getStringCellValue(colCell);
    				   if(value != null){
    					   value = value.trim();
    				   }			  
    				   String xmlColType = (String) curColMap.get("type");
    				   if(xmlColType.equals("int")){
    					   int   intVal = Integer.valueOf(value);
    					   curRowCellMap.put(curColCode, intVal);  //将这一行的数据以code-value的形式存入map
    				   }else{
    				      curRowCellMap.put(curColCode, value); 
    				   }
    				   /**验证cell数据**/
    				   validateCellData(i+1,j+1,colCell,entityName,headTitle,curColType);
    			   }
    			   listDatas.add(curRowCellMap);
    		   } 
    	   }
    	   
    	   if(this.getErrorString().length() ==0){//如果没有任何错误,就保存
    		   saveExcelData(entityName);
    		   System.out.println("导入数据成功!");
    	   }else{
    		   //清理所有的缓存clearMap();现在暂时未清理
    		   String[] strArr = errorString.toString().split("<br>");
    		   for(String s: strArr){
    			   System.out.println(s);
    		   }
    		   
    	   }
    	   
    	   
       }
       /**验证单元格数据**/
       @SuppressWarnings("static-access")
    public void validateCellData(int curRow,int curCol,HSSFCell colCell,String entityName,String headName,String curColType){
    	   
    	   List rulList = (List) parseXmlUtil.getColumnRulesMap().get(entityName+"_"+headName);
    	   if(rulList != null && rulList.size()>0){
    		   for(int i=0 ; i<rulList.size() ; i++){
    			   Map rulM = (Map) rulList.get(i);
    			   String rulName = (String) rulM.get("name");
    			   String rulMsg = (String) rulM.get("message");
    			   String cellValue = this.getStringCellValue(colCell).trim();		   		   
    			   if(rulName.equals(ParseConstans.RULE_NAME_NULLABLE)){		   
    				   
    				   if(cellValue.equals("")||cellValue == null){
    					   errorString.append("第"+curRow+"行,第"+curCol+"列:"+rulMsg+"<br>");
    				   }
    			   }else {
    				   //////这里写其他的验证规则。。。
    			   }
    		   }
    	   }
       }
       
       /**保存excel里面的数据**/
       @SuppressWarnings("unchecked")
    public void saveExcelData(String entityName){
    	   
           List<User> users= new ArrayList();
    	   for(int i = 0 ; i<this.getListDatas().size();i++){
    		   Map excelCol = (Map) this.getListDatas().get(i);  //得到第 i 行的数据	   
    		   User user = new User();
    		   try {
    			User obj = (User) BeanToMapUtil.convertMap(user.getClass(), excelCol);
    			users.add(obj);	 
    		} catch (IntrospectionException e) {			
    			e.printStackTrace();
    		} catch (IllegalAccessException e) {		
    			e.printStackTrace();
    		} catch (InstantiationException e) {		
    			e.printStackTrace();
    		} catch (InvocationTargetException e) {
    			e.printStackTrace();
    		}
    			  
    	   }
    	   /**批量保存数据**/
    	   Dao dao = new Dao();
    	   for(int i = 0;i<users.size();i++){
    		   try{
    		   dao.saveUser(users.get(i));
    		   
    		   }catch(Exception e){
    			   e.printStackTrace();
    		   }
    	   }
    	   
       }
       
       /**
    	 * 获得单元格字符串
    	 * @throws UnSupportedCellTypeException 
    	 */
    	public static String getStringCellValue(HSSFCell cell) {
    		if (cell == null){
    			return null;
    		}
    
    		String result = "";
    		switch (cell.getCellType()) {
    			case HSSFCell.CELL_TYPE_BOOLEAN:
    				result = String.valueOf(cell.getBooleanCellValue());
    				break;
    			case HSSFCell.CELL_TYPE_NUMERIC:
    				if (HSSFDateUtil.isCellDateFormatted(cell)) {
    					java.text.SimpleDateFormat TIME_FORMATTER = new java.text.SimpleDateFormat(
    							"yyyy-MM-dd");
    					result = TIME_FORMATTER.format(cell.getDateCellValue());
    				}
    				else{
    					double doubleValue = cell.getNumericCellValue();
    					result = "" + doubleValue;
    				}
    				break;
    			case HSSFCell.CELL_TYPE_STRING:
    				if (cell.getRichStringCellValue() == null){
    					result = null;
    				}
    				else{
    					result = cell.getRichStringCellValue().getString();
    				}
    				break;
    			case HSSFCell.CELL_TYPE_BLANK:
    				result = null;
    				break;
    			case HSSFCell.CELL_TYPE_FORMULA:
    				try{
    					result = String.valueOf(cell.getNumericCellValue());   
    		        }catch(Exception e){
    		        	result = cell.getRichStringCellValue().getString();
    		        }
    				break;
    			default:
    				result = "";
    		}
    		
    		return result;
    	}
    	/**主方法**/
    	public static void main(String[] args) {
    		
    		File excelFile = new File("src/user.xls");
    		File xmlFile = new File("src/user.xml");
            new ParseExcelUtil(excelFile,xmlFile);		
            
    	}
    
    	
    	
    	public String getCurEntityCode() {
    		return curEntityCode;
    	}
    	public void setCurEntityCode(String curEntityCode) {
    		this.curEntityCode = curEntityCode;
    	}
    	public Map getCurEntityHeadMap() {
    		return curEntityHeadMap;
    	}
    	public void setCurEntityHeadMap(Map curEntityHeadMap) {
    		this.curEntityHeadMap = curEntityHeadMap;
    	}
    	public ParseXMLUtil getParseXmlUtil() {
    		return parseXmlUtil;
    	}
    	public void setParseXmlUtil(ParseXMLUtil parseXmlUtil) {
    		this.parseXmlUtil = parseXmlUtil;
    	}
    	public Map getCurEntityColRequired() {
    		return curEntityColRequired;
    	}
    	public void setCurEntityColRequired(Map curEntityColRequired) {
    		this.curEntityColRequired = curEntityColRequired;
    	}
    	public List getListDatas() {
    		return listDatas;
    	}
    	public void setListDatas(List listDatas) {
    		this.listDatas = listDatas;
    	}
    	public StringBuffer getErrorString() {
    		return errorString;
    	}
    	public void setErrorString(StringBuffer errorString) {
    		this.errorString = errorString;
    	}
    
    
    }
    


    2.ParseXMLUtil.java

    这个类是用来解析xml的,测试方法同样可以右键 run as 运行。可以把下面的一段注释放开,查看打印结果。

    package com.karen.test2;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    /**
     * 解析xml工具类
     * @author PCCW-80352891
     *
     */
    @SuppressWarnings("rawtypes")
    public class ParseXMLUtil {
    
    	 /**entity map对象,key:name ,value:entity的属性map集**/
    	public Map entityMap ;
    	
    	/**column map 对象,key:entityName_colName , value:column的属性map集 **/
    	public Map columnMap;
    	
    	/**rule map 对象,key:entityName_colName_ruleName, value: rule 的map集:找到一行rule**/
    	public Map ruleMap ;
    	
    	/**rules map 对象, key:entityName_colName, value: rules 的map集:找到该column下所有的rule**/
    	public Map  columnRulesMap ;
    	
    	/**entity--column map: key:entityName, value: column list:根据实体类名得到所有的列**/
    	public Map columnListMap ;
    	
       /**column list**/
    	public List columnList ;
    	
    	 
        /**开始解析xml文件**/
    	public ParseXMLUtil(File xmlFilePath){
    		FileInputStream in = null;
    		try {
    			if(xmlFilePath == null){
    				 throw new FileNotFoundException();
    			}
    			SAXReader reader = new SAXReader();		           
               	in = new FileInputStream(xmlFilePath);	           	
    			Document doc = reader.read(in);
    			Element root = doc.getRootElement();	
    			Iterator itEntity = root.elements("entity").iterator();
    			while(itEntity.hasNext()){
    				Element entity = (Element) itEntity.next();
    				parseEntity(entity);
    			}
    			
    			/**测试entityMap 是否正确**/
    			Map enMap = (Map) this.getEntityMap().get("用户表");
    			Set<?> set = enMap.keySet();
    			Iterator it = set.iterator();
    			while(it.hasNext()){
    				String uu = (String) it.next();
    				System.out.println("entity properties:"+uu+" = "+enMap.get(uu));
    			}
    			
    /*			*//**测试column list是否正确**//*
    			List colList = (List) this.getColumnListMap().get("用户表");
    			System.out.println("column size:"+colList.size());
    			
    			*//**测试columnMap是否正确**//*
    			Map colMap = (Map) this.getColumnMap().get("用户表_员工号");						
    				Set<?> coListSet = colMap.keySet();
    				Iterator coListIt = coListSet.iterator();
    				while(coListIt.hasNext()){
    					String coListKey = (String) coListIt.next();
    					System.out.println("column  properties: "+coListKey+" = "+colMap.get(coListKey));
    				}		
    			*//**测试ruleMap是否正确**//*	
    			if(this.getColumnRulesMap() != null){
    			    List rulesValidList = (List) this.getColumnRulesMap().get("用户表_员工号");				
    				for(int i=0;i<rulesValidList.size(); i++){
    					Map colRuleMap = (Map) rulesValidList.get(i);
    				    String ruleName = (String) colRuleMap.get("name");
    				    Map ruleMa = (Map) this.getRuleMap().get("用户表_员工号_"+ruleName); //eg: 用户表_用户名_nullable
    				    String mess = (String) ruleMa.get("message");
    				    System.out.println("Validate Rules"+i+" : "+mess);							
    		  	    } 
    			}*/
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    		
    	}
    	
    	 /**开始解析entity**/
    	@SuppressWarnings("unchecked")
    	public void parseEntity(Element entity){
    		if(entity != null){
    			
    			/**对数据进行初始化设置**/
    			columnListMap = new HashMap();
    			columnMap = new HashMap();
    			entityMap = new HashMap();
    			ruleMap = new HashMap();
    			columnRulesMap = new HashMap();
    			columnList = new ArrayList();
    			
    			setEntityMap(entity);			
    			String entityName = entity.attributeValue("name");
    			Iterator itColumn = entity.elements("column").iterator();
    			while(itColumn.hasNext()){
    				Element column = (Element) itColumn.next();
    				setColumnMap(entityName,column);
    			}
    			columnListMap.put(entityName, columnList);
    		}
    	}
    	 
    	
    	
    	/**将entity放入entityMap中**/
    	@SuppressWarnings("unchecked")
    	public void setEntityMap(Element entity){		
    		Map ent = new HashMap();
    		String name = entity.attributeValue("name");
    		String code = entity.attributeValue("code");
    		ent.put("name", name);
    		ent.put("code", code);
    		entityMap.put(name, ent);			
    	}
    	
    	/**将column放入columnMap中**/
    	@SuppressWarnings("unchecked")
    	public void setColumnMap(String entityName,Element column){
    		if(column != null){		
    			Map col = new HashMap();
    			String name = column.attributeValue("name");
    			String code = column.attributeValue("code");
    			String type = column.attributeValue("type");
    			col.put("name", name);
    			col.put("code", code);
    			col.put("type", type);
    			String columnMapKey = entityName+"_"+name;    //eg:  用户表_用户名
    			columnMap.put(columnMapKey, col);		
    			columnList.add(col);
    			Iterator ruleIt = column.elements("rules").iterator();  //获得rules
    			while(ruleIt.hasNext()){
    				Element rules = (Element)ruleIt.next(); 
        			Iterator rule  = rules.elements("rule").iterator();   //获得 rule
        			while(rule.hasNext()){
        				Element ruleValid = (Element) rule.next();     //获得每一行rule
        				setRuleMap(entityName,name,ruleValid);    				
        			}
    			}
    		}
    	}
    		
        /**将 rule 验证规则放入ruleMap中**/
    	@SuppressWarnings("unchecked")
    	public void setRuleMap(String entityName,String columnName,Element ruleValid){
    		if(ruleValid != null){			
    			String ruleName = ruleValid.attributeValue("name");
    			String ruleMsg = ruleValid.attributeValue("message");
    			Map ruleValidMap = new HashMap();
    			ruleValidMap.put("name", ruleName);
    			ruleValidMap.put("message", ruleMsg);
    			String ruleStrKey = entityName+"_"+columnName+"_"+ruleName;
    			String colStrKey = entityName+"_"+columnName;
    			if(this.getColumnRulesMap().containsKey(colStrKey)){
        			List valids = (List) this.getColumnRulesMap().get(colStrKey);
        			valids.add(ruleValidMap);
        		}else{
        			List valids = new ArrayList();
        			valids.add(ruleValidMap);
        			this.columnRulesMap.put(colStrKey, valids);  //将每个column下的所有rules存入该map中
        		}
    			ruleMap.put(ruleStrKey, ruleValidMap); //将每个column下的一条rule存入该map中
    		}
    	}
    	
    	/**主方法**/
    	public static void main(String[] args) {
    		File file = new File("src/user.xml");
           new ParseXMLUtil(file);		
    	}
    
    	/**所有的get set 方法**/
    	public Map getEntityMap() {
    		return entityMap;
    	}
    
    	public void setEntityMap(Map entityMap) {
    		this.entityMap = entityMap;
    	}
    
    	public Map getColumnMap() {
    		return columnMap;
    	}
    
    	public void setColumnMap(Map columnMap) {
    		this.columnMap = columnMap;
    	}
    
    	public Map getRuleMap() {
    		return ruleMap;
    	}
    
    	public void setRuleMap(Map ruleMap) {
    		this.ruleMap = ruleMap;
    	}
    
    	public Map getColumnRulesMap() {
    		return columnRulesMap;
    	}
    
    	public void setColumnRulesMap(Map columnRulesMap) {
    		this.columnRulesMap = columnRulesMap;
    	}
    
    	public Map getColumnListMap() {
    		return columnListMap;
    	}
    
    	public void setColumnListMap(Map columnListMap) {
    		this.columnListMap = columnListMap;
    	}
    
    
    
    }
    


    3.既然做导入,当然需要连接数据库啦。只需要在mysql数据库中,建立一个 名为 chat 的数据库,然后导入下面的sql.来创建一张user表

    CREATE TABLE `user` (
      `status` varchar(20) default NULL,
      `port` int(10) NOT NULL,
      `ip` varchar(40) NOT NULL,
      `password` varchar(10) NOT NULL,
      `username` varchar(100) NOT NULL,
      `no` varchar(10) default NULL,
      `userImage` blob,
      PRIMARY KEY  (`username`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    4.例子肯定需要很多jar包,比如poi啊,各种包。我就不在这里写出来了。

     需要例子源码 请到这里下载:

    http://download.csdn.net/detail/chenxuejiakaren/4439307

    5.运行方法: 将例子导入到eclipse之中,然后可能会因为jdk版本不一样会有红色感叹号,没关系,改一下。单击项目右键--properties--java build path--libraries--找jdk啊。这个搞java的都会吧。

    然后,单击右键 run as 运行ParseExcelUtil.java 就可以啦。

    关于例子导入后会提示缺少包的问题:

    我引入的相关jar包是在eclipse里面直接引入的,没有相对于的lib目录。主要是缺少了2个jar

    poi-3.8-20120326.jar    下载地址:   http://download.csdn.net/detail/chenxuejiakaren/4440128

    mysql-connector-java-5.0.8-bin.jar      下载地址:  http://download.csdn.net/detail/chenxuejiakaren/4440132

    必须要在eclipse里引入他们。

  • 相关阅读:
    python2.7打印中文乱码的问题解决
    Tesseract5.0训练字库,提高OCR特殊场景识别率(一)
    git比较重要但是又容易忘记的操作
    ntp局域网时间同步操作
    Flask使用原生sql语句
    Linux的tail命令查看文件
    使用gitlab的webhook进行前端自动部署
    通过queue实现前端的被动接收
    互动interactive与多行输出
    复习
  • 原文地址:https://www.cnblogs.com/telwanggs/p/5340182.html
Copyright © 2020-2023  润新知