java中poi导出excel问题总结
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
- flush()下达一条命令给缓冲区,让它将所储存的数据全部清空,即发送给下一级。
- flush()刷空输出流,并输出所有被缓存的字节。由于某些流支持缓存功能,该方法将把缓存中所有内容强制输出到流中。
- 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
最后建议
在使用输出流时,在需要保存使用输出流的地方创建输出流对象。
更多推荐
所有评论(0)