在解析 apache poi 中的空单元格时获取 NPE


protected List<List<XSSFCell>> read2DTable(XSSFSheet sheet) {
    LOGGER.debug("read2DTable START");
    List<XSSFCell> headerCells = readTableHeader(sheet);
    List<List<XSSFCell>>  allRows = IntStream.range(sheet.getFirstRowNum(), sheet.getLastRowNum()+1)
                .mapToObj(i -> sheet.getRow(i))
                .map(row -> headerCells.stream()
                                       .map(col -> row.getCell(col.getColumnIndex()))
                                       .collect(Collectors.toList()))
                .filter(c -> StringUtils.isNotEmpty(c.toString()))
                .collect(Collectors.toList());
    LOGGER.info("rows read: {}, columns read: {}", allRows, headerCells.size());
    LOGGER.info("read2DTable END");
    return allRows;
}

这是错误:

 Caused by: java.lang.NullPointerException
        at com.netcracker.solutions.gtdc.cim.importdata.processing.excel.ExcelProcessor.lambda$null$9(ExcelProcessor.java:162)
        at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
        at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
        at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
        at com.netcracker.solutions.gtdc.cim.importdata.processing.excel.ExcelProcessor.lambda$read2DTable$10(ExcelProcessor.java:162)

这发生在这里:

     .map(col -> row.getCell(col.getColumnIndex()))
    .collect(Collectors.toList()))
.filter(c ->StringUtils.isNotEmpty(c.toString()))
.collect(Collectors.toList());

尝试替换:

StringUtils.isNotEmpty(c.toString())

跟:

StringUtils.isNotEmpty(null == c ? "" : c.toString())

或避免使用第三方库和更短的库(如 Holger 建议的那样(:

c!=null && !c.toString().isEmpty()

过滤所有空单元格:

List<List<XSSFCell>>  allRows = IntStream.range(sheet.getFirstRowNum(), sheet.getLastRowNum()+1)
        .mapToObj(i -> sheet.getRow(i))
        .map(row -> headerCells.stream()
                .map(col -> row.getCell(col.getColumnIndex()))
                .collect(Collectors.toList()))
        .filter(Obejcts::nonNull)
        .filter(c -> StringUtils.isNotEmpty(c.toString()))
        .collect(Collectors.toList());
一个

潜在的null候选者是getRow的结果,在.mapToObj(i -> sheet.getRow(i))年获得,但在.map(col -> row.getCell(col.getColumnIndex()))行中首先取消引用。

另请注意,最后一个filter是有问题的,因为您正在使用实用程序函数来测试可能null字符串的空性,但List.toString()的结果永远不会null,也永远不会为空,因为空List的表示形式将"[]"

固定代码如下所示:

List<List<XSSFCell>> allRows
  =IntStream.range(sheet.getFirstRowNum(), sheet.getLastRowNum()+1)
            .mapToObj(i -> sheet.getRow(i)) // you may also use .mapToObj(sheet::getRow)
            .filter(Objects::nonNull)
            .map(row -> headerCells.stream()
                                   .map(col -> row.getCell(col.getColumnIndex()))
                                   .collect(Collectors.toList()))
            .filter(list -> !list.isEmpty())
            .collect(Collectors.toList());

请注意,内部列表仍然可以包含null元素,具体取决于配置的MissingCellPolicy。将工作簿配置为始终获取空白单元格比从行列表中删除null元素更可取,以使所有行列表的列表索引对齐。

最新更新