是什么导致我的程序在写入 XSSF 工作簿时陷入困境?

What is causing my program to bog down when writing to XSSF Workbook?

也许“写”不是正确的词,因为在这个函数中,我只是设置单元格,然后再写。

我有一个功能,我已经指出这是它陷入困境的原因。当它到达这个函数时,它在这里花费了 10 多分钟,然后我才终止它。 这是我将 output_wb 传递给的函数:

private static void buildRowsByListOfRows(int sheetNumber, ArrayList<Row> sheet, Workbook wb) {
    Sheet worksheet = wb.getSheetAt(sheetNumber);
    int lastRow;
    Row row;
    String cell_value;
    Cell cell;
    int x = 0;
    System.out.println("Size of array list: " + sheet.size());
    for (Row my_row : sheet) {
        try {
            lastRow = worksheet.getLastRowNum();
            row = worksheet.createRow(++lastRow);

            for (int i = 0; i < my_row.getLastCellNum(); i++) {
                cell_value = getCellContentAsString(my_row.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK));
                cell = row.createCell(i);
                cell.setCellValue(cell_value);
                System.out.println("setting row #: " + x + "with value =>" + cell_value);
            }
            x++;
        } catch (Exception e) {
            System.out.println("SOMETHING WENT WRONG");
            System.out.println(e);
        }
    }
}

ArrayList 的大小是 73,835。它从 运行 开始非常快,然后到达 20,000 行左右,然后您可以看到循环中的打印语句越来越分散。每行有 70 列。

这个函数是真的写的那么差还是有什么问题? 我可以做些什么来优化它?

如果这很重要,我会像这样创建输出工作簿:

// Create output file with the required sheets 
createOutputXLSFile(output_filename_path);
XSSFWorkbook output_wb = new XSSFWorkbook(new FileInputStream(output_filename_path));

createOutputXLSFile() 看起来像这样:

private static void createOutputXLSFile(String output_filename_path) throws FileNotFoundException {
    try {
        // Directory path where the xls file will be created
        // Create object of FileOutputStream
        FileOutputStream fout = new FileOutputStream(output_filename_path);
        XSSFWorkbook wb = new XSSFWorkbook();
        wb.createSheet("Removed records"); 
        wb.createSheet("Added records"); 
        wb.createSheet("Updated records"); 

        // Build the Excel File
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        wb.write(outputStream);
        outputStream.writeTo(fout);
        outputStream.close();
        fout.close();
        wb.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
    private static String getCellContentAsString(Cell cell) {
        DataFormatter fmt = new DataFormatter();
        String data = null;
        if (cell.getCellType() == CellType.STRING) {
            data = String.valueOf(cell.getStringCellValue());
        } else if (cell.getCellType() == CellType.NUMERIC) {
            data = String.valueOf(fmt.formatCellValue(cell));
        } else if (cell.getCellType() == CellType.BOOLEAN) {
            data = String.valueOf(fmt.formatCellValue(cell));
        } else if (cell.getCellType() == CellType.ERROR) {
            data = String.valueOf(cell.getErrorCellValue());
        } else if (cell.getCellType() == CellType.BLANK) {
            data = String.valueOf(cell.getStringCellValue());
        } else if (cell.getCellType() == CellType._NONE) {
            data = String.valueOf(cell.getStringCellValue());
        }
        return data;
    }

更新#1- 似乎发生在这里。如果我注释掉所有 3 行然后它完成:

    cell_value = getCellContentAsString(my_row.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK));
    cell = row.createCell(i);
    cell.setCellValue(cell_value);

更新 #2 - 如果我注释掉这两行,那么循环将按预期完成:

    cell = row.createCell(i); // The problem
    cell.setCellValue(cell_value);

所以现在我知道问题出在 row.createCell(i) 但为什么呢?我该如何优化它?

我终于设法解决了这个问题。事实证明,如果文件很大,使用 XSSF 写入就太慢了。所以我将 XSSF 输出工作簿转换为 SXSSFWorkbook。为此,我只是将现有的 XSSFWorkbook 传递给 SXSSFWorkbook,如下所示:

        // Create output file with the required sheets 
        createOutputXLSFile(output_filename_path);
        XSSFWorkbook output_wb_temp = new XSSFWorkbook(new FileInputStream(output_filename_path));
        SXSSFWorkbook output_wb = new SXSSFWorkbook(output_wb_temp);

其余代码按原样工作。