编码技巧——导出工具类( 三 )


注意几种excel对象的不同:
第一种:
针对EXCEL 2003版本,扩展名为.xls,此种的局限就是导出的行数最多为65535行 。因为导出行数受限,不足7万行,所以一般不会发送内存溢出(OOM)的情况;
第二种:
这种形式的出现是由于第一种HSSF的局限性产生的,因为其导出行数较少,应运而生,其对应的是+ ,扩展名为.xlsx ,最多可以导出104万行,不过这样就伴随着一个问题–OOM内存溢出 。因为使用创建的book sheet row cell 等是存在内存中的,并没有持久化到磁盘上,那么随着数据量的增大,内存的需求量也就增大 。那么很有可能出现 OOM了,那么怎么解决呢?
第三种: 要求poi.jar 3.8+
可以根据行数将内存中的数据持久化写到文件中 。
此种的情况就是设置最大内存条数,比如设置最大内存量为5000行, new (5000),当行数达到 5000 时,把内存持久化写到文件中,以此逐步写入,避免OOM 。这样就完美解决了大数据下导出的问题;
API文档:POI核心类 -POI教程?
应用中我们一般使用后2种,本篇讲的是,而不推荐旧格式的,因为打开文件可能存在兼容性问题、单个sheet的总行书受限65535;
(5)实现类-导出为csv:

编码技巧——导出工具类

文章插图
package com.AA.common.utils.exporter;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang.StringUtils;import java.io.*;import java.nio.charset.Charset;import java.util.List;/*** @author AA* @description cvs文件导出工具* @date 2021/3/9*/@Slf4jpublic class CsvExporter extends AbstractFileExporter {/*** 字节流*/private ByteArrayOutputStream byteArrayOutputStream;/*** 字节流输出*/private PrintWriter printWriter;/*** 初始化导出工具** @param clazz*/@Overridevoid initExporter(Class clazz) {byteArrayOutputStream = new ByteArrayOutputStream(20 * 1024 * 1024);printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, Charset.forName("GBK")));List headers = getHeaders(clazz);printWriter.println(StringUtils.join(headers, ","));}/*** 填充数据行,数据可以是不对齐的** @param rows*/@Overridevoid writeRows(List rows) {rows.forEach(row -> {printWriter.println(StringUtils.join(row, ","));});printWriter.flush();}/*** 写输出流** @param outputStream*/@Overridepublic void writeStream(OutputStream outputStream) {if (outputStream == null) {log.warn("outputStream is null!");return;}byte[] bytes = byteArrayOutputStream.toByteArray();try {outputStream.write(bytes);} catch (IOException e) {log.error("failed to write ByteArrayStream! e:{}", e.getMessage(), e);} finally {try {printWriter.close();byteArrayOutputStream.close();} catch (IOException e) {log.error("failed to close ByteArrayStream! e:{}", e.getMessage(), e);}}}}
csv和xlsx有什么分別?
一个是逗号分割的文本文件,一个是标准的表格文件 。CSV本质上就是一个文本文件,无任何格式,但Excel却是一个带有格式的数据表格文件 。Excel有最大行数限制,但CSV没有 。二者可以相互转化 。
参考:csv和xlsx有什么分別? - 知乎
因此,仅对于导出数据存储上,csv文件相比xlsx,占用内存更小,导出更快;07版以后的Excel本质上是xml,这一点可以在修改后缀为.rar验证;
(6)从excel读取数据的工具类:
【编码技巧——导出工具类】import com.google.common.collect.Lists;import lombok.extern.slf4j.Slf4j;import org.apache.poi.ss.usermodel.CellType;import org.apache.poi.xssf.usermodel.*;import org.springframework.web.multipart.MultipartFile;import java.io.InputStream;import java.util.*;/*** @author AA* @description excel解析工具类*/@Slf4jpublic class ExcelReaderUtil {/*** excel文件类型后缀*/public static final String OFFICE_EXCEL_XLSX = ".xlsx";/*** 读取excel行数的最大值,防止OOM*/private static final int MAX_READABLE_LINE_COUNT = 1000;/*** 解析XSSFSheet,从起始行start到结束行end,取出指定列column的item放入list返回** @param xssfSheet* @param column列数,从0计数* @param rowStart起始行(闭区间)* @param rowEnd结束行(开区间)* @return*/public static List getListFrXSSFSheet(XSSFSheet xssfSheet, int column, int rowStart, int rowEnd) {List result = Lists.newArrayList();try {XSSFRow xssfRow;XSSFCell xssfCell;for (int row = rowStart; row