Poi(适合小数据量)
Apache POI 官网:https://poi.apache.org/
POI是Apache软件基金会的,POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。
所以POI的主要功能是可以用Java操作Microsoft Office的相关文件,这里我们主要讲Excel
小数据写
1 .导入依赖
<dependencies><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.17</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.17</version></dependency><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>2.10.1</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.1</version></dependency></dependencies>
2 .开启读写操作,代码走起
无非就是对api的充分认识,接下来我们先去了解他的api
Workbook wordkbook =new HSSFWorkbook();//创建一个Workbook对象wordkbook.createSheet();//创建表名,如果不写参数,会有默认值Row row1=sheet.createRow(0);//根据里面的数字拿到对应的行,0默认为第一行Cell cell = row1.createCell(0);//根据行对象创建单元格,这里0为第一个cell.setCellValue("");//可以给单元格赋值
写入一个Excel
package com.kuang;import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.DateTime;
import org.junit.Test;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class ExcelWriteTest {//先要有个路劲static String path="D:\JAVA---EasyExcel\TEST";@Testpublic void testWrite03(String[] args) throws IOException {//1,创建一个工作薄Workbook wordkbook =new HSSFWorkbook();//表名Sheet sheet=wordkbook.createSheet("灰灰统计表");//创建行Row row1=sheet.createRow(0);//4.创建一个单元格Cell cell = row1.createCell(0);cell.setCellValue("今日新增观众");Cell cell2 = row1.createCell(1);cell2.setCellValue("卢本伟");//创建行Row row2=sheet.createRow(1);//4.创建一个单元格Cell cell3 = row2.createCell(0);cell3.setCellValue("统计时间");Cell cell24= row2.createCell(1);String time=new DateTime().toString("yyyy-MM-dd HH:mm:ss");cell24.setCellValue(time);//生成一张表 03是xls 07是xlsxFileOutputStream fileOutputStream = new FileOutputStream(path + "灰灰统计表03.xls");wordkbook.write(fileOutputStream);fileOutputStream.close();System.out.println("灰灰统计表03已生成");}@Testpublic void testWrite07() throws IOException {//1,创建一个工作薄Workbook wordkbook =new XSSFWorkbook();//表名Sheet sheet=wordkbook.createSheet("灰灰统计表");//创建行Row row1=sheet.createRow(0);//4.创建一个单元格Cell cell = row1.createCell(0);cell.setCellValue("今日新增观众");Cell cell2 = row1.createCell(1);cell2.setCellValue("卢本伟");//创建行Row row2=sheet.createRow(1);//4.创建一个单元格Cell cell3 = row2.createCell(0);cell3.setCellValue("统计时间");Cell cell24= row2.createCell(1);String time=new DateTime().toString("yyyy-MM-dd HH:mm:ss");cell24.setCellValue(time);//生成一张表 03是xls 07是xlsxFileOutputStream fileOutputStream = new FileOutputStream(path + "\灰灰统计表07.xlsx");wordkbook.write(fileOutputStream);fileOutputStream.close();System.out.println("灰灰统计表07已生成");}}
上面写完后会在项目目录下生成一个表格
03 | 07 版本的写,就是对象不同,方法一样的!
大数据写
HSSF
缺点:最多只能处理65536行,否则会抛出异常
java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0…65535)
优点:过程中写入缓存,不操作磁盘,最后一次性写入磁盘,速度快
@Test
public void testWrite03BigData() throws IOException {long begin = System.currentTimeMillis();HSSFWorkbook workbook = new HSSFWorkbook();HSSFSheet sheet = workbook.createSheet();for (int rowNum = 0; rowNum < 65535; rowNum++) {Row row = sheet.createRow(rowNum);for (int cellNum = 0; cellNum < 10; cellNum++) {Cell cell = row.createCell(cellNum);cell.setCellValue(cellNum);}}System.out.println("over");FileOutputStream outputStream = new FileOutputStream(path + "//testWrite03BigData");workbook.write(outputStream);outputStream.close();long end = System.currentTimeMillis();System.out.println((double) (end-begin)/1000);}
XSSF
缺点:写数据时速度非常慢,非常耗内存,也会发生内存溢出,如100万条
优点:可以写较大的数据量,如20万条
@Test
public void testWrite07BigData() throws IOException {long begin = System.currentTimeMillis();Workbook workbook = new XSSFWorkbook();Sheet sheet = workbook.createSheet();for (int rowNum = 0; rowNum < 655350; rowNum++) {Row row = sheet.createRow(rowNum);for (int cellNum = 0; cellNum < 10; cellNum++) {Cell cell = row.createCell(cellNum);cell.setCellValue(cellNum);}}System.out.println("over");FileOutputStream outputStream = new FileOutputStream(path + "//testWrite03BigData.xlsx");workbook.write(outputStream);outputStream.close();long end = System.currentTimeMillis();System.out.println((double) (end-begin)/1000);}
SXSSF
优点:可以写非常大的数据量,如100万条甚至更多条,写数据速度快,占用更少的内存
注意:
过程中会产生临时文件,需要清理临时文件
默认由100条记录被保存在内存中,如果超过这数量,则最前面的数据被写入临时文件 如果想自定义内存中数据的数量,可以使用new SXSSFWorkbook ( 数量 )
@Test
public void testWrite07BigDataS() throws IOException {long begin = System.currentTimeMillis();Workbook workbook = new SXSSFWorkbook();Sheet sheet = workbook.createSheet();for (int rowNum = 0; rowNum < 100000; rowNum++) {Row row = sheet.createRow(rowNum);for (int cellNum = 0; cellNum < 10; cellNum++) {Cell cell = row.createCell(cellNum);cell.setCellValue(cellNum);}}System.out.println("over");FileOutputStream outputStream = new FileOutputStream(path + "//testWrite07BigDataS.xlsx");workbook.write(outputStream);outputStream.close();((SXSSFWorkbook)workbook).dispose();//关闭临时文件long end = System.currentTimeMillis();System.out.println((double) (end-begin)/1000);}
SXSSFWorkbook-来至官方的解释:实现“BigGridDemo”策略的流式XSSFWorkbook版本。这允许写入 非常大的文件而不会耗尽内存,因为任何时候只有可配置的行部分被保存在内存中。
请注意,仍然可能会消耗大量内存,这些内存基于您正在使用的功能,例如合并区域,注释…仍然只存 储在内存中,因此如果广泛使用,可能需要大量内存。
读取单一类型的数据
这个操作跟上述的写并没有什么不同,不同就是方法是get而不是set
static String path="F:\\demo\\javapoi\\demopoi";@Testpublic void testRead03() throws IOException {//Sheet sheet=workbook.createSheet("统计表");//sheet操作表中元素FileInputStream fileInputStream = new FileInputStream(path + "\灰灰统计表03.xls");Workbook workbook=new HSSFWorkbook(fileInputStream);Sheet sheet = workbook.getSheetAt(0);
// Sheet sheet2 = workbook.getSheet("灰灰统计表");Row row = sheet.getRow(1);Cell cell = row.getCell(0);Cell cell2 = row.getCell(1);System.out.println(cell.getStringCellValue());System.out.println(cell2.getStringCellValue());fileInputStream.close();}
这里值得注意的是,使用表格对象要注意三种创建方式
- POI-HSSF
- POI-XSSF
- SXSSF
**HSSF:*Excel97-2003版本,扩展名为.xls。一个sheet最大行数*65536,最大列数256。
**XSSF:*Excel2007版本开始,扩展名为.xlsx。一个sheet最大行数*1048576,最大列数16384。
SXSSF:**是在XSSF基础上,POI3.8版本开始提供的**支持低内存占用的操作方式,扩展名为.xlsx。
Excel版本兼容性是向下兼容。
读取不同类型的数据
在读取数据的时候我们需要先判断值类型,才能用对应API
下面这个是先拿到表头那一行,相当于数据库的字段
FileInputStream fileInputStream = new FileInputStream(path + "数据表07.xlsx");Workbook workbook=new XSSFWorkbook(fileInputStream);Sheet sheet = workbook.getSheetAt(0);Row rowTitle = sheet.getRow(0);if(rowTitle!=null){int cellCount=rowTitle.getPhysicalNumberOfCells(); //拿到第row行的那一行的总个数for (int i = 0; i <cellCount ; i++) { //循环个数取出Cell cell = rowTitle.getCell(i);if(cell!=null){ //如果不等于空取出值int cellType = cell.getCellType(); //这里是知道我们标题是String,考虑不确定的时候怎么取String cellValue = cell.getStringCellValue();System.out.print(cellValue+"|");}}System.out.println();}
下面接着读取对应的数据,这里就需要我们刚刚讲的类型判断
int cellType=cell.getCellType();利用这个,然后判断它的XSSFCell类型再具体输出
//获取表中内容int rowCount=sheet.getPhysicalNumberOfRows();for(int rowNum=1;rowNum<rowCount;rowNum++){Row rowData=sheet.getRow(rowNum); //取出对应的行if(rowData!=null){int cellCount=rowTitle.getPhysicalNumberOfCells();for(int cellNum=0;cellNum<cellCount;cellNum++){System.out.print("["+(rowNum+1+"-"+(cellNum+1)+"]"));Cell cell = rowData.getCell(cellNum);//匹配数据类型if(cell!=null){int cellType=cell.getCellType();switch (cellType){case XSSFCell.CELL_TYPE_STRING: System.out.print("字符串:"+cell.getStringCellValue());break;case XSSFCell.CELL_TYPE_BOOLEAN: System.out.print("布尔:"+cell.getBooleanCellValue());break;case XSSFCell.CELL_TYPE_NUMERIC:if(HSSFDateUtil.isCellDateFormatted(cell)){System.out.println("日期格式:"+new DateTime(cell.getDateCellValue()).toString("yyyy-MM-dd HH:mm:ss"));break;}elsecell.setCellType(XSSFCell.CELL_TYPE_STRING);System.out.print("整形:"+cell.toString());break;case XSSFCell.CELL_TYPE_BLANK: System.out.print("空");break;case XSSFCell.CELL_TYPE_ERROR: System.out.print("数据类型错误");break;case Cell.CELL_TYPE_FORMULA://拿到计算公式XSSFFormulaEvaluator FormulaEvaluator = new XSSFFormulaEvaluator((XSSFWorkbook) workbook);String formula=cell.getCellFormula();System.out.println("公式:"+formula);//CellValue evaluate = FormulaEvaluator.evaluate(cell);String cellValue=evaluate.formatAsString();System.out.println(cellValue);break;default:break;}}}}}fileInputStream.close();