poi工具读写excel操作学习总结
写在前面的话
POI作为比较早期的Excel处理工具,其使用较为成熟且广泛。EasyExcel相较之下,则是相对较新的工具,其却有着比POI更为优越的一些特性,如更加简单的API接口和更加优秀的性能。
性能对比:在数据量较小的情况下,POI和EasyExcel的性能表现较为相似,但在数据量较大的情况下,EasyExcel要比POI具有更快的速度。这主要得益于EasyExcel内部优化的使用反射技术,避免了POI中频繁创建Cell和Row等对象时的性能问题。
API对比:在API接口使用上,EasyExcel相较于POI也更为简单直观。POI的API接口使用较为繁琐,需要使用大量的行列、坐标等信息来操作Excel表格数据,而EasyExcel则将其进行了封装和优化,使其更加易用和方便。
简单易用性对比:EasyExcel相较于POI也更具有易用性和灵活性。EasyExcel的代码量较POI更少并且更为优美,使得开发者能够更容易的上手使用和进行二次封装,同时EasyExcel还支持自定义注解的方式进行Excel表格数据和Java对象之间的映射关系,使其在应用场景上更加丰富多彩。
其他方面的对比:POI和EasyExcel也有着各自的优缺点。如在对于老版本的Excel文件的支持上,POI更胜一筹;而在对于较为复杂的Excel表格数据处理方面,POI则有着更多的功能和接口可供探索,EasyExcel的功能相对较为局限。
1.poi简单写操作
03版本,结尾是:.xls,03和07版本的主要区别是能写的数据量大小,03版本只能写65536行,07版本基本没限制。03版本对象是:HSSFWorkbook。07版本对象是:XSSFWorkbook。
/**
* poi,excel03版本
* @throws IOException
*/
@Test
public void test03() throws IOException {
String PATH = "D:\\code\\excel";
//首先创建一个工作簿
HSSFWorkbook work = new HSSFWorkbook();
//然后创建一个工作表
HSSFSheet sheet = work.createSheet("weiqinag");
//其次创建一个行(1,1)
HSSFRow row = sheet.createRow(0);
//其次再创建一个单元格,坐标(1,1)单元格
HSSFCell cell11 = row.createCell(0);
cell11.setCellValue("我是第一个单元格");
//坐标(1,2)单元格
HSSFCell cell12 = row.createCell(1);
cell12.setCellValue("我是第一行第二个单元格");
//坐标(2,1)
HSSFRow row1 = sheet.createRow(1);
HSSFCell cell21 = row1.createCell(0);
cell21.setCellValue("我是第二行一个单元格");
//坐标(2,2)
HSSFCell cell22 = row1.createCell(1);
String string = new DateTime().toString("yyyy-MM--dd HH:mm:ss");
cell22.setCellValue(string);
//生成一张表(IO)流,03版本的是xls结尾
FileOutputStream fileOutputStream = new FileOutputStream(PATH +"\\"+"weiqiang03.xls");
work.write(fileOutputStream);
//关闭流
fileOutputStream.close();
System.out.println("excel生成完毕");
}
07版本,结尾是:.xlsx
可以看到只是对象变化了,03版本的对象是 HSSFWorkbook,07版本的对象是XSSFWorkbook,接口没有变化,这就是面向对象的好处之一。
@Test
public void test07()throws Exception{
String PATH = "D:\\code\\excel";
//首先创建一个工作簿07版本
XSSFWorkbook work = new XSSFWorkbook();
//然后创建一个工作表
Sheet sheet = work.createSheet();
//其次创建一个行(1,1)
Row row = sheet.createRow(0);
//其次再创建一个单元格,坐标(1,1)单元格
Cell cell11 = row.createCell(0);
cell11.setCellValue("我是第一个单元格");
//坐标(1,2)单元格
Cell cell12 = row.createCell(1);
cell12.setCellValue("我是第一行第二个单元格");
//坐标(2,1)
Row row1 = sheet.createRow(1);
Cell cell21 = row1.createCell(0);
cell21.setCellValue("我是第二行一个单元格");
//坐标(2,2)
Cell cell22 = row1.createCell(1);
String string = new DateTime().toString("yyyy-MM--dd HH:mm:ss");
cell22.setCellValue(string);
//生成一张表(IO)流,03版本的是xlsx结尾
FileOutputStream fileOutputStream = new FileOutputStream(PATH +"\\"+"weiqiang07.xlsx");
work.write(fileOutputStream);
//关闭流
fileOutputStream.close();
System.out.println("excel生成完毕");
}
2.大文件写操作
对于大文件写操作来说,03版本的缺点是最多处理65536行,否则会排除异常,优点是过程中写入缓存,不操作磁盘,最后一次性写入磁盘,速度快。
07版本的缺点是写数据非常慢,非常耗内存,会发生内存溢出的异常,如100万条,优点是可以写较大的数据量,如20万条,远远大于03版本的65536行。
2.1 03版本大文件写
HSSFWorkbook对象大数据写操作,总耗时是1.3秒左右,很快。
@Test
public void test03BigData() throws IOException {
String PATH = "D:\\code\\excel";
long begin = System.currentTimeMillis();
HSSFWorkbook workbook = new HSSFWorkbook();
Sheet sheet = workbook.createSheet();
for (int rowNum = 0; rowNum <65536 ; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("循环完毕,开始写");
FileOutputStream fileOutputStream = new FileOutputStream(PATH+"\\"+"bigDate.xls");
workbook.write(fileOutputStream);
fileOutputStream.close();
long end = System.currentTimeMillis();
System.out.println("消耗时间:"+(double)(end - begin)/1000);
}
2.2 07版本大文件写
XSSFWorkbook对象大数据写操作,总耗时达到6.5秒左右,很慢。
@Test
public void test07BigData() throws IOException {
long begin = System.currentTimeMillis();
String PATH = "D:\\code\\excel";
XSSFWorkbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
for (int rowNum = 0; rowNum < 65536; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("循环结束,开始写操作");
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "\\" + "bigdate07.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
long end = System.currentTimeMillis();
System.out.println("消耗时间:" + (double) (end - begin) / 1000);
}
2.2 SXSSF大文件写操作
根据前两个比较,03版本虽然快,但是数据量有限制,07版本的数量大,但是速度慢,那有没有速度快又写入数据量大的对象呢?有,那就是SXSSF对象,他可以写非常大的数据量,如100万条以上,写数据速度快,占用内存更少。写数据100000行,用时2.5秒左右。是不是非常快,还要记得一点,利用SXSSF对象会有临时文件产生,需要清除临时文件。
@Test
public void testBigData() throws IOException {
long begin = System.currentTimeMillis();
String PATH = "D:\\code\\excel";
SXSSFWorkbook 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("循环结束,开始写输出流写操作");
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "\\" + "bigdate.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
//清除临时文件
((SXSSFWorkbook)workbook).dispose();
long end = System.currentTimeMillis();
System.out.println("消耗时间:" + (double) (end - begin) / 1000);
}
3.读操作
3.1 03版本excel表的读操作
读操作,首先获取文件流,然后把流放入工作簿中,其次得到这个表,再得到行和列,最后得到行列坐标的值。读取值的时候一定要注意值的类型,否则出错。
@Test
public void testRead03() throws IOException {
String PATH = "D:\\code\\excel";
//获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH + "\\" + "weiqiang03.xls");
//首先创建一个工作簿,把流放到工作簿里
HSSFWorkbook work = new HSSFWorkbook(fileInputStream);
//然后得到表
Sheet sheet = work.getSheetAt(0);
//得到行和得到列
Cell cell = sheet.getRow(0).getCell(0);
//得到坐标的值
System.out.println(cell.getStringCellValue());
}
3.2 07版本excel表读操作
只需要换对象即可
@Test
public void testRead03() throws IOException {
String PATH = "D:\\code\\excel";
//获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH + "\\" + "weiqiang03.xls");
//首先创建一个工作簿,把流放到工作簿里
XSSFWorkbook work = new XSSFWorkbook(fileInputStream);
//然后得到表
Sheet sheet = work.getSheetAt(0);
//得到行和得到列
Cell cell = sheet.getRow(0).getCell(0);
//得到坐标的值
System.out.println(cell.getStringCellValue());
}
3.3 读取不同类型的数据(难点)
/**
* 把该类封装成工具类,直接调用该方法时,传递参数fileInputStream就行了
* @param fileInputStream
* @throws Exception
*/
@Test
public void testRead(FileInputStream fileInputStream)throws Exception{
String PATH = "D:\\code\\excel";
//首先获取文件流,读取哪个文件
// fileInputStream = new FileInputStream(PATH + "\\" + "03.xls");
//首先创建一个工作簿07版本进行读,也可以用03版本读取,但是03文件是xls,所以用03版本读取
HSSFWorkbook work = new HSSFWorkbook(fileInputStream);
//然后获取这工作表
Sheet sheetAt = work.getSheetAt(0);
//获取第一行,就是标题
Row rowTitle = sheetAt.getRow(0);
//获取第一行的所有标题
if (rowTitle != null) {
//获取第一行所有的列
int cellCount = rowTitle.getPhysicalNumberOfCells();
//遍历,取出每列的内容,就是具体标题
for (int cellNum = 0; cellNum < cellCount; cellNum++) {
//获取列
Cell cell = rowTitle.getCell(cellNum);
if (cell != null) {
//获取列类型
int cellType = cell.getCellType();
//现在默认是是String类型,一般第一行都是字符串
String stringCellValue = cell.getStringCellValue();
System.out.print(stringCellValue+" | ");
}
}
System.out.println();
}
//获取表中的内容,先获取所有的行
int rows = sheetAt.getPhysicalNumberOfRows();
//rowNum =1 是从第二行开始,第一行是标题
for (int rowNum = 1; rowNum < rows; rowNum++) {
//获取每行的数据
Row rowData = sheetAt.getRow(rowNum);
//读取列,每行的每列
if (rowData != null) {
int cells = rowTitle.getPhysicalNumberOfCells();
for (int cellsNum = 0; cellsNum < cells; cellsNum++) {
System.out.print("["+(rowNum+1)+"-"+(cellsNum+1)+"]");
//拿到每行每列的数据
Cell cell = rowData.getCell(cellsNum);
//匹配列的数据类型
if (cell != null) {
CellType cellType = cell.getCellTypeEnum();
String cellValue= "";
switch (cellType) {
case STRING:
System.out.print("String类型");
cellValue = cell.getStringCellValue();
break;
case BOOLEAN:
System.out.print("布尔类型");
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case BLANK:
System.out.print("空格");
break;
case NUMERIC:
System.out.print("数字类型");//需要区分是数字还是日期
if (HSSFDateUtil.isCellDateFormatted(cell)) {
System.out.print("日期");
Date date = cell.getDateCellValue();
cellValue = new DateTime(date).toString("yyyy-MM--dd");
} else {
//不是日期格式,防止数字过长
System.out.print("转换为字符串输出");
cell.setCellType(CellType.STRING);
cellValue = cell.toString();
}
break;
case ERROR:
System.out.print("数据类型错误");
break;
}
System.out.println(cellValue);
}
}
}
}
fileInputStream.close();
}
4.EasyExcel读写操作
学习完poi操作Excel后,感觉是有一些困难,不太方便,所以继续学习阿里巴巴开源下的EasyExcel工具,该工具就是简单高效,会发现代码很简洁。
4.1准备一个Student类
@Data
//@ContentRowHeight(20)//内容行高
//@HeadRowHeight//表头行高
public class Student {
@ExcelProperty(value = "ID",index = 4)//表头顺序
@ExcelIgnore
private Integer sno;
@ExcelProperty("姓名")
private String sname;
@ExcelProperty("年龄")
@ColumnWidth(20)
private Integer sage;
@ExcelProperty("性别")
private String ssex;
@DateTimeFormat("yyyy-MM-dd")
private Date birthday;
}
4.2 EasyExcel读操作
public class StudentListener extends AnalysisEventListener<Student> {
/**
* 读监听器,每读一行内容,都会调用一次该对象的invoke,在invoke中可以操作使用读取到的数据。
* @param student 每次读取到的数据封装对象
* @param analysisContext
*/
@Override
public void invoke(Student student, AnalysisContext analysisContext) {
System.out.println("student = "+student);
}
/**
* 读取完整的文档之后调用的方法
* @param analysisContext
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
/**
* 读操作,从excel表格读操作,也就是导入操作。
*/
@Test
public void testRead(){
/*
构建一个工作簿对象
pathName 要读的文件的路径
head 文件中每一行的数据
redaListener 读监听器
*/
//获得一个工作簿对象
ExcelReaderBuilder read = EasyExcel.read("student.xlsx", Student.class, new StudentListener());
//获得一个工作表的对象
ExcelReaderSheetBuilder sheet = read.sheet();
//读取工作表中的内容
sheet.doRead();
}
4.3 EasyExcel写操作
/**
* 写操作,向excel文件中写内容,也就是导出操作
*/
@Test
public void testWrite() {
//首先是获取一个工作簿,和poi一样
ExcelWriterBuilder writeWorkBook = EasyExcel.write("student-write.xls", Student.class);
//然后是获取一个工作表
ExcelWriterSheetBuilder sheet = writeWorkBook.sheet();
//最后是写入到excel表中
List<Student> students = intData();
System.out.println(students);
sheet.doWrite(students);
}
public static List<Student> intData(){
ArrayList<Student> students = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Student student = new Student();
student.setSname("哈哈"+i);
student.setSno(i);
student.setSage(20+i);
student.setSsex("男");
students.add(student);
}
System.out.println(students);
return students;
}
完!
原文地址:https://blog.csdn.net/qq_35207086/article/details/136345097
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!