使用easyexcel操作Excel

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/babyyaoyao/article/details/82854801

我也是凑巧用上了,就在这里分享一下,性能确实是没得说!

对easyexcel的介绍是:Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到KB级别,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便 

1、导入的pom.xml

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel</artifactId>
        <version>1.0.3</version>
    </dependency>

实际上版本(1.0.1)在读取的时候是有BUG的,读取03版的.xls格式的excel正常,但是读取07版的.xlsx版的excel就会出异常,原因是在解析的时候sheet临时文件路径拼装有误,所以我们用1.0.3

2、使用easyexcel读取excel的时候需要设置excel的版本,但是有些时候我们无法预知excel的版本,所以在网上copy了大神模仿poi写了一个用于获取com.alibaba.excel.ExcelReader对象的工具类

package easyExcel.com.easy.excel;

import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;

import org.apache.poi.EmptyFileException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.IOUtils;

import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.context.AnalysisContext;
import com.alibaba.excel.read.event.AnalysisEventListener;
import com.alibaba.excel.support.ExcelTypeEnum;

public class ExcelReaderFactory {
   /**
    * @param in
    *           文件输入流
    * @param customContent
    *           自定义模型可以在
    *           {@link AnalysisEventListener#invoke(Object, AnalysisContext) }
    *           AnalysisContext中获取用于监听者回调使用
    * @param eventListener
    *           用户监听
    * @throws IOException
    * @throws EmptyFileException
    * @throws InvalidFormatException
    */
   public static ExcelReader getExcelReader(InputStream in, Object customContent,
         AnalysisEventListener<?> eventListener) throws EmptyFileException, IOException, InvalidFormatException {
      // 如果输入流不支持mark/reset,需要对其进行包裹
      if (!in.markSupported()) {
         in = new PushbackInputStream(in, 8);
      }

      // 确保至少有一些数据
      byte[] header8 = IOUtils.peekFirst8Bytes(in);
      ExcelTypeEnum excelTypeEnum = null;
      if (NPOIFSFileSystem.hasPOIFSHeader(header8)) {
         excelTypeEnum = ExcelTypeEnum.XLS;
      }
      if (DocumentFactoryHelper.hasOOXMLHeader(in)) {
         excelTypeEnum = ExcelTypeEnum.XLSX;
      }
      if (excelTypeEnum != null) {
         return new ExcelReader(in, excelTypeEnum, customContent, eventListener);
      }
      throw new InvalidFormatException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");

   }

   /**
    * @param in
    *           文件输入流
    * @param customContent
    *           自定义模型可以在
    *           {@link AnalysisEventListener#invoke(Object, AnalysisContext) }
    *           AnalysisContext中获取用于监听者回调使用
    * @param eventListener
    *           用户监听
    * @param trim
    *           是否对解析的String做trim()默认true,用于防止 excel中空格引起的装换报错。
    * @throws IOException
    * @throws EmptyFileException
    * @throws InvalidFormatException
    */
   public static ExcelReader getExcelReader(InputStream in, Object customContent,
         AnalysisEventListener<?> eventListener, boolean trim)
         throws EmptyFileException, IOException, InvalidFormatException {
      // 如果输入流不支持mark/reset,需要对其进行包裹
      if (!in.markSupported()) {
         in = new PushbackInputStream(in, 8);
      }

      // 确保至少有一些数据
      byte[] header8 = IOUtils.peekFirst8Bytes(in);
      ExcelTypeEnum excelTypeEnum = null;
      if (NPOIFSFileSystem.hasPOIFSHeader(header8)) {
         excelTypeEnum = ExcelTypeEnum.XLS;
      }
      if (DocumentFactoryHelper.hasOOXMLHeader(in)) {
         excelTypeEnum = ExcelTypeEnum.XLSX;
      }
      if (excelTypeEnum != null) {
         return new ExcelReader(in, excelTypeEnum, customContent, eventListener, trim);
      }
      throw new InvalidFormatException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");
   }
}

3、然后编写一个简单的测试类

package easyExcel.com.easy.excel;

import java.io.FileInputStream;
import java.io.InputStream;

import org.junit.Test;

import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.read.context.AnalysisContext;
import com.alibaba.excel.read.event.AnalysisEventListener;

public class ExcelWriteTest {

    public static class ExcelPropertyIndexModel extends BaseRowModel {
		@ExcelProperty(value = "姓名", index = 0)
		private String name;

		@ExcelProperty(value = "年龄", index = 1)
		private String age;

		@ExcelProperty(value = "邮箱", index = 2)
		private String email;

		@ExcelProperty(value = "地址", index = 3)
		private String address;

		@ExcelProperty(value = "性别", index = 4)
		private String sax;

		@ExcelProperty(value = "高度", index = 5)
		private String heigh;

		@ExcelProperty(value = "备注", index = 6)
		private String last;

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getAge() {
			return age;
		}

		public void setAge(String age) {
			this.age = age;
		}

		public String getEmail() {
			return email;
		}

		public void setEmail(String email) {
			this.email = email;
		}

		public String getAddress() {
			return address;
		}

		public void setAddress(String address) {
			this.address = address;
		}

		public String getSax() {
			return sax;
		}

		public void setSax(String sax) {
			this.sax = sax;
		}

		public String getHeigh() {
			return heigh;
		}

		public void setHeigh(String heigh) {
			this.heigh = heigh;
		}

		public String getLast() {
			return last;
		}

		public void setLast(String last) {
			this.last = last;
		}

		@Override
		public String toString() {
			return "ExcelPropertyIndexModel [name=" + name + ", age=" + age + ", email=" + email + ", address="
					+ address + ", sax=" + sax + ", heigh=" + heigh + ", last=" + last + "]";
		}
		
	}

	@Test
	public void read() throws Exception {
		//text.xlsx
		try (InputStream in = new FileInputStream("try.xlsx");) {
			AnalysisEventListener<ExcelPropertyIndexModel> listener = new AnalysisEventListener<ExcelPropertyIndexModel>() {

				@Override
				public void invoke(ExcelPropertyIndexModelobject, AnalysisContext context) {
					System.err.println("Row:" + context.getCurrentRowNum() + " Data:" 
				+ object.toString());
				}

				@Override
				public void doAfterAllAnalysed(AnalysisContext context) {
					System.err.println("doAfterAllAnalysed...");
				}
			};
			ExcelReader excelReader = ExcelReaderFactory.getExcelReader(in, null, listener);
			// 第二个参数为表头行数,按照实际设置
			excelReader.read(new Sheet(1, 1, ExcelPropertyIndexModel.class));
		}
	}
}

解释一下测试类的代码:ExcelPropertyIndexModel是一个用来存放解析完表格的数据类,@ExcelProperty(value = "名称", index = 10)注解中的index标识着这个参数对应的列,index从0开始

猜你喜欢

转载自blog.csdn.net/babyyaoyao/article/details/82854801