目录

  • 一、简介
  • 二、maven依赖
  • 三、工具类ExcelUtil
  • 四、测试
    • 4.1、EmployeeVo
    • 4.2、写入数据到Excel
    • 4.3、从Excel读取数据
  • 结语

一、简介

  HSSFWorkbook 、 XSSFWorkbook 、SXSSFWorkbook三者的区别

  • HSSFWorkbook:是操作Excel 2003以前(包括2003)的版本,扩展名是.xls,数据限制是65535,超过则内存溢出
  • XSSFWorkbook:是操作Excel 2007后的版本,扩展名是.xlsx,数据限制是1048576行,16384列,超过则内存溢出
  • SXSSFWorkbook:是操作Excel 2007后的版本,扩展名是.xlsx,从POI 3.8版本开始可以持久化到磁盘,减少内存溢出问题

  我们写个工具不仅能直接把简单Java对象数据直接导出到Excel,还能把数据读取成我们需要的简单的Java对象,并且可以根据你的需要选择不同的 Workbook,不用纠结HSSFWorkbook 、 XSSFWorkbook 、SXSSFWorkbook分别怎么用,本文中 org.apache.poi 使用的版本是 5.0.0。

二、maven依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.2</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.alian</groupId><artifactId>excel</artifactId><version>0.0.1-SNAPSHOT</version><name>excel</name><description>Java实现Excel文件读写</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.0.0</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.0.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.14</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>compile</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

  最重要的依赖就是下面两个

   <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.0.0</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.0.0</version></dependency>

三、工具类ExcelUtil

ExcelUtil.java

package com.alian.excel.utils;import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;@Slf4j
public class ExcelUtil {/*** 从Excel读取数据返回对象集合** @param filePath         文件路径* @param t                java对象* @param filterRowNumbers 过滤行数(比如数据的头部一行就不是数据)* @param <T>              泛型* @return List<T>*/public static <T> List<T> readDataFromExcel(String filePath, Class<T> t, int filterRowNumbers) {FileInputStream fis = null;ArrayList<T> list = new ArrayList<>();try {fis = new FileInputStream(filePath);Workbook sheets = WorkbookFactory.create(fis);//获取sheet第一页(根据自己需要)Sheet sheet = sheets.getSheetAt(0);//获取表格的行数int totalRowNumber = sheet.getPhysicalNumberOfRows();//获取对象的字段列表Field[] fields = t.getDeclaredFields();for (int i = filterRowNumbers; i < totalRowNumber; i++) {//获取一行数据Row row = sheet.getRow(i);//实例对象放到循环内(这个bug是网友【starwenran】提到的,网址【https://blog.csdn.net/weixin_42345741】)T obj = t.newInstance();
//              //变量一行数据的每个单元格,row.getPhysicalNumberOfCells()是单元格的数量for (int j = 0, jLen = row.getPhysicalNumberOfCells(); j < jLen; j++) {Cell cell = row.getCell(j);//获取字段Field dataField = fields[j];String startWord = dataField.getName().substring(0, 1);//需要注意的是如果变量是is开头的Boolean类型,它的set方法不能用下面的,因为它的set方法是去掉is的方法//比如isEnable,set方法是setEnableString methodName = "set" + dataField.getName().replaceFirst(startWord, startWord.toUpperCase());//获取字段的set方法,dataField.getType()是参数的类型Method method = t.getMethod(methodName, dataField.getType());//反射调用set方法,getValueFromCell是把表格的值转成对应的类型method.invoke(obj, getValueFromCell(dataField, cell));}list.add(obj);}return list;} catch (Exception e) {log.error("从Excel读取数据异常", e);return Collections.emptyList();} finally {try {if (fis != null) {fis.close();}} catch (IOException e) {e.printStackTrace();}}}/*** 把数据导入到Excel(支持HSSFWorkbook、XSSFWorkbook、SXSSFWorkbook)** @param workbook    工作薄* @param sheetName   sheet名称* @param headerArray 头部标签数据* @param list        数据list* @param filePath    数据导出路径* @param <T>         泛型*/public static <T> void exportDataToExcel(Workbook workbook, String sheetName, String[] headerArray, List<T> list, String filePath) {//生成一个表格,并命名Sheet sheet = workbook.createSheet(sheetName);//设置表格默认列宽15个字节sheet.setDefaultColumnWidth(15);//生成一个头部样式CellStyle headerStyle = getCellStyle(workbook, true);//生成表格标题Row headerRow = sheet.createRow(0);headerRow.setHeight((short) 300);for (int i = 0, len = headerArray.length; i < len; i++) {//创建头部行的一个小单元格Cell headerRowCell = headerRow.createCell(i);//设置头部单元格的样式headerRowCell.setCellStyle(headerStyle);//设置头部单元格的值headerRowCell.setCellValue(headerArray[i]);}//获取数据域样式CellStyle bodyStyle = getCellStyle(workbook, false);FileOutputStream os = null;try {//将数据放入sheet中for (int i = 0, iLen = list.size(); i < iLen; i++) {//创建一行,因为头部已经占用一行故需要加1Row dataRow = sheet.createRow(i + 1);T t = list.get(i);//利用反射,根据JavaBean属性的先后顺序,动态调用get方法得到属性的值Field[] fields = t.getClass().getDeclaredFields();try {for (int j = 0, jLen = fields.length; j < jLen; j++) {//获取单元格第值Cell dataRowCell = dataRow.createCell(j);//获取字段Field dataField = fields[j];String startWord = dataField.getName().substring(0, 1);//需要注意的是如果变量是is开头的Boolean类型,它的get方法不能用下面的,因为它的get方法是去掉is的方法//比如isEnable,get方法是getEnableString methodName = "get" + dataField.getName().replaceFirst(startWord, startWord.toUpperCase());//获取对象的get方法Method getMethod = t.getClass().getMethod(methodName);//反射调用get方法Object value = getMethod.invoke(t);//单元格值为StringdataRowCell.setCellValue(null == value ? "" : value.toString());dataRowCell.setCellStyle(bodyStyle);}} catch (Exception e) {log.error("第【{}】行数据生成异常(下标0开始)", i, e);}}os = new FileOutputStream(filePath);workbook.write(os);os.flush();} catch (Exception e) {log.error("生成数据异常", e);} finally {try {if (os != null) {os.close();}} catch (IOException e) {log.error("关闭文件异常", e);}}}/*** 获取单元格样式** @param workbook 工作薄* @param isHeader 是否是头部标签* @return CellStyle*/public static CellStyle getCellStyle(Workbook workbook, boolean isHeader) {CellStyle style = workbook.createCellStyle();//设置边框style.setBorderBottom(BorderStyle.THIN);style.setBorderTop(BorderStyle.THIN);style.setBorderLeft(BorderStyle.THIN);style.setBorderRight(BorderStyle.THIN);//设置边框颜色style.setLeftBorderColor(IndexedColors.BLACK.getIndex());style.setRightBorderColor(IndexedColors.BLACK.getIndex());style.setTopBorderColor(IndexedColors.BLACK.getIndex());style.setBottomBorderColor(IndexedColors.BLACK.getIndex());//水平对齐方式style.setAlignment(HorizontalAlignment.CENTER);//垂直对齐方式style.setVerticalAlignment(VerticalAlignment.CENTER);//设置字体样式Font font = workbook.createFont();font.setColor(IndexedColors.BLACK.getIndex());font.setFontHeightInPoints((short) 12);if (isHeader) {//设置背景色style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());style.setFillPattern(FillPatternType.SOLID_FOREGROUND);font.setFontHeightInPoints((short) 14);font.setBold(true);}//把字体应用到当前样式style.setFont(font);return style;}/*** 把数据转成对象字段相应的类型(待完善:其他类型的判断,默认值及为空判断)** @param dataField* @param cell* @return*/public static Object getValueFromCell(Field dataField, Cell cell) {String fieldTypeStr = dataField.getType().toString();if (fieldTypeStr.contains("String")) {return cell.getStringCellValue();} else if (fieldTypeStr.contains("Integer") || fieldTypeStr.contains("int")) {return Integer.parseInt(cell.getStringCellValue());} else if (fieldTypeStr.contains("Boolean") || fieldTypeStr.contains("boolean")) {return Boolean.getBoolean(cell.getStringCellValue());} else if (fieldTypeStr.contains("Double") || fieldTypeStr.contains("double")) {return Double.parseDouble(cell.getStringCellValue());} else if (fieldTypeStr.contains("float")) {return Float.parseFloat(cell.getStringCellValue());} else if (fieldTypeStr.contains("Long") || fieldTypeStr.contains("long")) {return Long.parseLong(cell.getStringCellValue());} else if (fieldTypeStr.contains("char")) {return cell.getStringCellValue().charAt(0);} else if (fieldTypeStr.contains("LocalTime")) {return LocalTime.parse(cell.getStringCellValue());} else if (fieldTypeStr.contains("LocalDate")) {return LocalDate.parse(cell.getStringCellValue());} else if (fieldTypeStr.contains("LocalDateTime")) {return LocalDateTime.parse(cell.getStringCellValue());} else if (fieldTypeStr.contains("Date")) {try {return new SimpleDateFormat("yyyy-MM-dd").parse(cell.getStringCellValue());} catch (ParseException e) {log.error("时间转化异常", e);}}return null;}}

  工具类中使用到了反射的知识,来完成get和set方法的操作。最近太忙了,都没有更新博客了,这个是修订后的版本,多谢网友【starwenran】的留言提醒,因为存数据的时候,随意造了重复数据,没检查读出的结果,造成读出的数据是最后一行数据,【starwenran】的博客地址是:https://blog.csdn.net/weixin_42345741,当然这个工具类还有他的不足,比如对is开头的Boolean对象的处理(本文注释中有说明),以后有时间我再优化下。

四、测试

4.1、EmployeeVo

EmployeeVo.java

package com.alian.excel.vo;import lombok.Data;import java.io.Serializable;
import java.time.LocalDate;@Data
public class EmployeeVo {/*** 员工编号*/private String id;/*** 员工姓名*/private String name;/*** 员工年龄*/private int age;/*** 工资*/private double salary;/*** 部门*/private String department;/*** 入职时间*/private LocalDate hireDate;/*** 无参构造函数不能少*/public EmployeeVo(){}public EmployeeVo(String id, String name, int age, double salary, String department, LocalDate hireDate) {this.id = id;this.name = name;this.age = age;this.salary = salary;this.department = department;this.hireDate = hireDate;}
}

4.2、写入数据到Excel

我们写个测试类

    @Testpublic void write() {List<EmployeeVo> dataList = new ArrayList<>();//仅仅是模拟数据for (int i = 10000; i < 10030; i++) {EmployeeVo employeeVo = new EmployeeVo("BAT"+i,"梁南生",18,20000.0,"研发部",LocalDate.of(2020,2,13));dataList.add(employeeVo);}String sheetName = "员工信息";String[] headerArray = new String[]{"员工编号", "员工姓名", "员工年龄", "工资", "部门", "入职时间"};String filePath = "C:\\myFile\\CSDN\\Excel\\Excel文件写入测试.xls";ExcelUtil.exportDataToExcel(new HSSFWorkbook(), sheetName, headerArray, dataList, filePath);//ExcelUtil.exportDataToExcel(new XSSFWorkbook(), sheetName, headerArray, dataList, filePath);//ExcelUtil.exportDataToExcel(new SXSSFWorkbook(),sheetName, headerArray, dataList, filePath);}

运行结果:

如果你用HSSFWorkbook 写入的数据大于65535则会报错

 17:02:37.541 [main] ERROR com.alian.excel.utils.ExcelUtil - 生成数据异常java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)

4.3、从Excel读取数据

    @Testpublic void read() {String filePath = "C:\\myFile\\CSDN\\Excel\\Excel文件写入测试.xls";List<EmployeeVo> employeeVos = ExcelUtil.readDataFromExcel(filePath, EmployeeVo.class, 1);log.info("读取的数据行数:{}",employeeVos.size());for (EmployeeVo employeeVo:employeeVos){log.info("{}",employeeVo);}}

运行结果:

19:54:37.313 [main] INFO com.alian.excel.service.TestExcelService - 读取的数据行数:30
19:54:37.316 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10000, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10001, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10002, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10003, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10004, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10005, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10006, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10007, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10008, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10009, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10010, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10011, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10012, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10013, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10014, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10015, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10016, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10017, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10018, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10019, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10020, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10021, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10022, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10023, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10024, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10025, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10026, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10027, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10028, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)
19:54:37.317 [main] INFO com.alian.excel.service.TestExcelService - EmployeeVo(id=BAT10029, name=梁南生, age=18, salary=20000.0, department=研发部, hireDate=2020-02-13)

结语

  本工具类是针对简单Java对象实现读写的,尽量不要使用继承之类的,假设你的对象实现了序列化接口,可能就要对字段 serialVersionUID进行排除。还有就是各种类型的转换并没有写全(只包括常见类型),包括数据空值处理等,大家可以根据需要进行调整。

  本文是先写入再读取,因为写入时字段的类型是字符串,所以读取的时候会转为对象相应的类型,Excel里的格式本身就是很复杂的,所以使用本工具类时,最好是使用本工具写入的,或者先把数据的格式先转为文本格式再使用。

  如果你对账文件处理,建议还是使用CSV文件,参考:Java实现CSV文件的读写(包含追加内容)

Java实现Excel文件读写相关推荐

  1. java中 Excel文件解析及超大Excel文件读写

    本文主要对Excel中数据的解析和生成进行总结 前言 在应用程序的开发过程中,我们经常要用到Excel进行数据的导入或导出.所以,在通过Java语言实现此类需求时,通常会对Excel文件进行解析或生成 ...

  2. 高级知识点:excel4j实现java操作excel文件的读写

    介绍 java操作excel文件最经典的是POI,但是其api 较多,代码量巨大,反复重复 excel4j ap则简洁太多,利用pojo建模,利用注解进行标识@ExcelField(title = & ...

  3. java对excel经行读写

    java对excel经行读写 package com.common.tool.util;import org.apache.poi.hssf.usermodel.*; import org.apach ...

  4. EasyExcel实现对excel文件读写

    EasyExcel实现对excel文件读写 1.EasyExcel介绍 2.EasyExcel特点: 3.EasyExcel写操作 3.1 pom中引入xml相关依赖 3.2 创建实体类 3.3 实现 ...

  5. 超详细的java生成excel文件并下载

    在网上随手一搜,可以搜到很多java生成excel文件相关的博客,但每个都有不同,核心点说清楚了,但具体运用的时候,相信大家或多或少都没法一次直接运用,这样每次去找并且运用的时候很费时间,所以这也是我 ...

  6. 【Apache POI】Java写入Excel文件

    上篇文章学习了Java读取Excel文件,这篇文章接着来简单总结Java写入Excel,话不多说,看代码: import java.io.File; import java.io.FileInputS ...

  7. java流与文件——读写二进制数据(DataOutput + DataInput)

    [0]README 0.1) 本文描述转自 core java volume 2, 旨在理解 java流与文件--读写二进制数据(DataOutput + DataInput)的相关知识: 0.2) ...

  8. java写入excel文件poi

    java写入excel文件 java写入excel文件poi,支持xlsx与xls,没有文件自动创建 package com.utils;import java.io.File; import jav ...

  9. python第三方库文件传输_Python第三方库在Excel文件读写中的应用

    Python第三方库在Excel文件读写中的应用 文/刘卫华1 史婷婷2 许学添1 [摘 要]摘 要 [期刊名称]<电子技术与软件工程> [年(卷),期]2019(000)016 [总页数 ...

最新文章

  1. 怎样使用计算机上的高级共享设置密码,win7系统电脑,如何设置共享,共享计算机的用户名和密码怎样设置...
  2. android显示服务器端文件夹,Android上传文件到服务端并显示进度条
  3. spring的log4j listener(webAppRootKey)
  4. python循环post请求_循环post请求太多
  5. c语言飞机订票系统设计,飞机订票系统设计
  6. Linux下如何查看tomcat是否启动
  7. 创建图书管理_阿拉尔市文化(图书)馆举办总分馆制建设图书管理软件、文化云专题培训班...
  8. vue-cli2.0+webpack 项目搭建
  9. mysql 中like怎么用_mysql中like怎么用?
  10. 爬虫第七课:python爬取淘宝商品评论
  11. SegmentFault 社区访谈 | Felix:一个如同空气般存在的人
  12. 软件需求工程2018期末题
  13. PMP考试 工作绩效数据 工作绩效信息 工作绩效报告 区别与联系
  14. 专用5G网络的7种部署方案
  15. Unity3D游戏开发入门学习笔记
  16. linux的基础简答题,Linux认证考试试题及答案「简答题」
  17. 从CSDN账户密码被盗说起
  18. code.aliyun.com拉取提交代码认证失败
  19. 【Wiki】XWiki数据备份
  20. 抖音实战~首页视频~下拉刷新

热门文章

  1. Ruby‘s Adventrue游戏制作笔记(十六)Unity子弹数量及其UI
  2. Java学习笔记09从认识多态开始
  3. MAC |如何在mac上阅读caj文件?
  4. BlackAndWhiteChess
  5. 2020腾讯Android岗初级到高级面试真题收录解析,七年老Android掏心分享
  6. 在线考试系统设计时必须考虑的问题之一------------批改试卷问题
  7. 非计算机专业特别是人文社科,中职非计算机专业《计算机应用基础》教学必须重视学情分析...
  8. Query parameters 查询参数
  9. SMO优化支持向量机
  10. 小程序自动化之minium