java中poi导出excel问题总结

java中poi导出excel问题总结

代码情况

使用的是XSSFWorkbook对象,但经过一系列的方法转为WorkBook对象
最后写入的方式是:
OutputStream output=null;
因为业务需要 在业务代码开始前output已经进行赋值
下面代码是使用流的情况进行导出

		output=response.getOutputStream();
                    workbook.write(output);
                    workbook.close();
                    output.flush();
                    output.close();
需注意问题1: output.flush();

这个操作的解释:
解释链接 http://www.51gjie.com/java/703.html

  1. flush()下达一条命令给缓冲区,让它将所储存的数据全部清空,即发送给下一级。
  2. flush()刷空输出流,并输出所有被缓存的字节。由于某些流支持缓存功能,该方法将把缓存中所有内容强制输出到流中。
  3. OutputStream.flush()方法将所有写入到OutputStream的数据冲刷到相应的目标媒介中。比如,如果输出流是FileOutputStream,那么写入到其中的数据可能并没有真正写入到磁盘中。即使所有数据都写入到了FileOutputStream,这些数据还是有可能保留在内存的缓冲区中。通过调用flush()方法,可以把缓冲区内的数据刷新到磁盘(或者网络,以及其他任何形式的目标媒介)中。

我的理解就是清空缓存,更详细的理解; https://blog.csdn.net/xzj80927/article/details/79802711

需注意问题2: 数据量较大时

我遇到的问题是 :当数据量很小时sql查询的很快,所以导出数据也很速度,但当数据量较大时(当前需求需要导出1万5左右的数据,但业务需要,会把数据进行处理,所以进行业务计算的时间就需要较长时间,暂没有时间优化,所以先解决导出情况),查询速度很慢时就会遇到报错的情况
情况:

1. 出现在excel导入的时候
2. 线上有问题,本地数量少时不可重现
3. 数据量少的时候没问题,POI excel基本超过10000行就出现问题
4. 查看日志,提示Broken pipe

解决方案:
当接口加载时间过长时,可能会遇到 nginx 和 负载均衡 的限制
nginx和负载均衡 一般限制时间为60s
错误:POI导出大批量数据出现Broken pipe
设置nginx的参数 将原先的60s给为 90s 或者180s

proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;

参考:nginx设置参考 https://www.osheep.cn/4825.html

下面是负载的参考:
线上项目导出数据慢且有时出现闪退现象原因分析及解决办法
https://blog.csdn.net/liaomingwu/article/details/107778828

负载的话我是没有设置的
因为当前项目我是用的外网访问的,所以内网的情况下是别人负载,
如果当前你也是这种情况,就联系负责的运维人员

需注意问题3: 本地环境和测试环境都可以,生产却不行

(本地和测试和生产的代码一致)
我遇到的就是接口加载时间较长,当本地和测试环境都不报错,使用内网访问postman访问也没有问题,
这种情况下就是 上面我说的,看看nginx和负载设置的大小和时间

需注意问题4:workbook.write(outputStream)无法写入数据

下面这个情况是我解决我的问题看到别人的解释:
链接如下,可以参考下(我觉得影响不大,我的项目代码就是这样写的也没有影响)
POI workbook.write(outputStream)无法写入数据
https://bbs.csdn.net/topics/392504634

需注意问题5 org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException: Fail to save: an error occurs while saving the package : The part /xl/worksheets/sheet1.xml fail to be saved in the stream with marshaller org.apache.poi.openxml4j.opc.internal.marshallers.DefaultMarshaller@4b4bf13c

这个错误 参考
参考1 : https://blog.csdn.net/m0_37607945/article/details/107270405?spm=1001.2101.3001.6650.12&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-12-107270405-blog-105681227.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-12-107270405-blog-105681227.pc_relevant_paycolumn_v3&utm_relevant_index=14
参考2: 代码位置原因 https://blog.csdn.net/qq_34075488/article/details/85272825

需注意问题6:getOutputStream和getWriter 的方法关系

如果你用了OutputStream,而web容器生成的servlet代码中有out.write(””),这个和JSP中调用的
response.getOutputStream()冲突。out.write()这个是字符流,而response.getOutputStream()是字节流,你不能在同一个页面中调用多个输出流
参考1:https://blog.csdn.net/csdn1161851523/article/details/52872083
参考2 : https://blog.csdn.net/weixin_39901571/article/details/114116701?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2aggregatepagefirst_rank_ecpm_v1~rank_v31_ecpm-2-114116701-null-null.pc_agg_new_rank&utm_term=Java%E5%AF%BC%E5%87%BA%E6%96%87%E4%BB%B6%E5%90%8E+%E6%8A%A5%E9%94%99%3Aresponse%E6%83%85%E5%86%B5outputStream&spm=1000.2123.3001.4430

需注意问题 7: java.lang.IllegalStateException

当前我使用的框架为JFinal
下载文件后后台报错:(核心提示)java.lang.IllegalStateException: Committed
解决方法
在代码中 添加 renderNull();

原因
response是服务端对客户端请求的一个响应,对于当前页面中已经committed(提交)的response,就不能再使用这个response向缓冲区写任何东西,否则会有IllegalStateException的异常。
因为程序默认调用render()方法,会将response再次使用,以向客户端发出响应,导致报错 而 JFinal手册中指出,renderNull表示不向客户端返回数据

参考 :https://blog.csdn.net/xingxinglaile/article/details/38704499

参考问题 :XSSFWorkbook和SXSSFWorkbook两个对象读取模板
1. 首先关于java导出Excel最大限制是65535行 如果超出这个行数的话 就会报错 HSSF最大限制 65535行
2. XSSF最大限制,100W行 使用HSSF的话,要不就在下一个sheet写入,要不就是用XSSF格式导出,要不就改成csv的后缀 csv最大限制的行数是1000w行
3. HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls;
4. XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx; 
5. XSSFWorkbook对象可以来读取模板然后将数据填充在读取的模板中,是当你数据量过大时,官方XSSFWorkbook说最多导出65535行,但实际可能达不到这个数量就会报OOM(内存溢出)的错误了
6. SXSSFWorkbook导出大数据量的数据(104W+)但是SXSSFWorkbook不能支持直接读取模板了,也就是说我们直接使用此对象无法读取模板的内容。
7. SXSSFWorkbook它旨在将行刷新到磁盘而不是将其保存在内存中。

参考:https://blog.csdn.net/weixin_41968562/article/details/107105129
解决java poi海量数据导出内存溢出问题 : https://blog.csdn.net/YiWangJiuShiXingFu/article/details/80258148

字符输出流 (Write)

java.io.Write:字符输出流是所有字符输出流的最顶层的父类是一个抽象类
字符输出流的使用步骤

1、创建Filewrite对象构造方法中绑定要写入数据的目的地

2、使用Filewrite中的方法write把数据写入到内存缓冲区中(字符转换为字节的过程)

3、使用Filewrite的方法flush把内存缓冲区的数据写入到文件中

4、释放资源(会先把内存缓冲区的数据刷新的文件中)

flush方法和close方法的区别

——flush:刷新缓冲去,流对象可以继续使用

——close:先刷新缓冲区再通知系统释放资源 ,流对象不可再使用了

参考 :https://blog.csdn.net/m0_62938286/article/details/123939273

最后建议

在使用输出流时,在需要保存使用输出流的地方创建输出流对象。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Apache POI框架来实现JavaPOI导出Excel功能,以下是一个示例代码: ``` import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExcelExporter { public static void main(String[] args) { XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet("Sample sheet"); Object[][] data = { {"John", 28}, {"Doe", 30}, {"William", 35}, {"Alex", 21}, {"Lucas", 18}, }; int rowNum = 0; System.out.println("Creating excel"); for (Object[] rowData : data) { Row row = sheet.createRow(rowNum++); int columnNum = 0; for (Object field : rowData) { Cell cell = row.createCell(columnNum++); if (field instanceof String) { cell.setCellValue((String) field); } else if (field instanceof Integer) { cell.setCellValue((Integer) field); } } } try { FileOutputStream outputStream = new FileOutputStream("sample.xlsx"); workbook.write(outputStream); outputStream.close(); System.out.println("Excel created successfully"); } catch (IOException e) { e.printStackTrace(); } } } ``` 这个代码使用了XSSFWorkbook类来创建一个Excel工作簿,然后使用createSheet()方法在工作簿创建一个新的表单。之后,我们定义了一个包含数据的二维数组,并将数据插入表单。最后,我们使用FileOutputStream类将文件输出到磁盘上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值