本文由网络易云社区发布,该社区获得作者xldxm的许可。
欢迎来到网络易云社区。 我想了解更多网易技术产品的运营经验。
昨天,一项业务反馈显示,报价信息导出失败。 查看日志,在导出记录到Excel时报告了NullpointException异常。 错误的是,在以下方法中,红色标记的代码(dataRow为null ) :
专用语音下载(sheet,intendRowNum,introwNum ) if (endrownumrownum ) rowdatarow=sheet.getrow ) ) for(inti=0; i8; I ) {cellcell=datarow.getcell(I; If (蜂窝!=null } { sheet.addmergedregion (newcellrangeaddress (rownum,endRowNum,I,I ) }; }}}}
此方法的作用是将rowNum行到endRowNum的第一列到第七列进行单元格合并。 我多次检查代码和数据,除了数据量大以外,在某个地方没有发现dataRow为null。 通过调试终于知道了原因。 让我们记录一下这个问题。
简要说明导出的业务。 导出的信息包括商品、供应商和供应商的报价。 一个商品可以包含多个供应商信息,每个供应商可以有多个报价。 Excel的格式如下:
因此,如果一个商品支持多个供应商和报价,则需要将商品和供应商的信息合并到单元格中。 在单元格中写入数据的步骤是,首先在第rowNum行中写入商品信息,然后写入供应商信息和报价信息,合并供应商信息,返回最后一个行号endRowNum,最后用上述方法将商品属性单元格合并报告异常的那个商品总共有1739件的估计,数量有点多。
向Excel写入数据时,数据首先保存在SXSSFSheet的_Rows中。 _rows是TreeMapInteger、SXSSFRow和Key是行(row )的索引,从0开始依次增加1、2、3 .Value是相应的断点,_rows中的数据Key是739 算上1739份数据,里面只有后面的1000份。 在以下调试中,如果_rows中有1000多条数据,并且在其中插入另一条数据,则size仍为1000,但第一条数据将被挤出。
我看了SXSSFSheet中createRow的方法,找到了原因。 代码如下。
publicsxssfrowcreaterow (int rownum )……sxssfrownewrow=newsxsfrow (this,initialAllocationSize ); this._ rows.put (integer.value of (rownum ),newRow ); this.allFlushed=false; if (this._ randomaccesswindowsize=0this._ rows.size (this._ randomaccesswindowsize ) try { this.flush rows } } }返回新建;参数rownum是行的后缀,也是_rows的密钥。 代码发现创建新行时,将调用this.flush rows (this._ randomaccesswindowsize )。 通过方法名称可以看出方法应该起到刷新缓存等作用。 flushRows方法的代码如下:
publicvoidflushrows (int remaining ) throwsioexception (while ) this._ rows.size (remaining ) { this.flushonerow } this }} flushOneRow方法的代码如下: 隐私保护软件() throwsioexception (integerfirstrownum
= (Integer)this._rows.firstKey();//取出最小的key if(firstRowNum != null) { int rowIndex = firstRowNum.intValue(); SXSSFRow row = (SXSSFRow)this._rows.get(firstRowNum); this._writer.writeRow(rowIndex, row);// this._rows.remove(firstRowNum); this.lastFlushedRowNumber = rowIndex; } }通过代码可以看到,flushOneRow方法里会取出key最小的一条数据,写入文件中,然后从_rows中删除,让_rows一直维持在1000的大小。
这就解释了为什么放入了1739条数据,_rows中只有1000条,并且存在的都是后面的。
所以当调用sheet.getRow(rowNum)去取那些从_rows删掉的数据就会返回null。
从源码中可以看到,默认情况下_rows的size是保持在100的,而非1000.
可以通过构造函数进行修改:
免费体验云安全(易盾)内容安全、验证码等服务
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 Android事件分发机制浅析(1)
【推荐】 从细节处谈Android冷启动优化
【推荐】 MongoDB之我是怎么成为Primary节点的