【问题标题】:FileOutputStream (Apachhe POI) taking too long time to saveFileOutputStream (Apache POI) 保存时间过长
【发布时间】:2015-04-10 02:50:49
【问题描述】:

当我使用 Apache poi 编辑 .xlsx 文件时,保存时间太长。 .xlsx 文件包含公式格式和冻结窗格。我正在使用以下代码,

try {
            FileInputStream file = new FileInputStream(new File(path));
            XSSFWorkbook fWorkbook = new XSSFWorkbook(file);
            XSSFSheet fSheet = fWorkbook.getSheetAt(0);

            for(int i = 0; i < jTable1.getRowCount(); i++){
                if(jTable1.getModel().getValueAt(i, index1).equals("1")){
                    XSSFCell cell = fSheet.getRow(i+1).getCell(index1);
                    cell.setCellType(XSSFCell.CELL_TYPE_NUMERIC);
                    cell.setCellValue(new Double(1));
                    XSSFCellStyle cs = fWorkbook.createCellStyle();
                    cs.setDataFormat(fWorkbook.getCreationHelper().createDataFormat().getFormat("dd/MMMM/yyyy"));
                    cell =fSheet.getRow(i+1).getCell(index2);
                    cell.setCellValue(new Date());
                    cell.setCellStyle(cs);
                }
            }
            file.close();
            FileOutputStream fileOutputStream = new FileOutputStream(path);
            fWorkbook.write(fileOutputStream);
            fileOutputStream.close();
            JOptionPane.showMessageDialog(this, "Data saved successfully.");
            parent.removeContent();
        }catch(Exception e){
            e.printStackTrace();
        }

编辑 1:

excel文件:http://ge.tt/5orGWSJ2/v/0?c

从 Excel 将数据加载到 JTable 中:

try {
                FileInputStream file1 = new FileInputStream(new File("c:\\sample.xlsx"));
                XSSFWorkbook workbook = new XSSFWorkbook(file1);
                XSSFSheet sheet = workbook.getSheetAt(0);
                int rowc=sheet.getLastRowNum()+1;
                int colc=sheet.getRow(0).getLastCellNum();
                Object heading[] = new Object[colc+1];
                XSSFRow row1 = sheet.getRow(0);
                for(int i=0, column =0; i < colc; i++){
                    if(i == 1){
                        heading[column++] = "";
                    }
                    heading[column++] = cellToString(row1.getCell(i));
                }
                Object [][]j=new Object[rowc-1][colc+1];

                for (int i = 1; i < rowc; i++) {
                    row1 = sheet.getRow(i); 
                    for (int jj = 0, column = 0; jj < colc; jj++) {
                        if(column == 1){
                            j[i-1][column++] = new Boolean(false);
                            j[i-1][column] = cellToString(row1.getCell(jj));
                        }
                        else{
                            j[i-1][column]=cellToString(row1.getCell(jj));
                        }
                        column++;
                    }
                }

                jTable1.setModel(new DefaultTableModel(j, heading){
                    public Class getColumnClass(int columnIndex) {
                        if(columnIndex == 0){
                            return java.lang.Integer.class;
                        }
                        else if(columnIndex == 1){
                            return java.lang.Boolean.class;
                        }
                        else{
                            return java.lang.Object.class;
                        }
                    }
                });

                jTable1.getColumnModel().getColumn(1).setMaxWidth(60);
                jTable1.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
                jTable1.getTableHeader().setReorderingAllowed(false);
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(BarcodePrint.this, ex);
            }

编辑列BarcodePrint后将数据写入excel:

try {   
            FileInputStream file = new FileInputStream(new File("c:\\sample.xlsx"));
            XSSFWorkbook fWorkbook = new XSSFWorkbook(file);
            XSSFCellStyle cs = fWorkbook.createCellStyle();
            cs.setDataFormat(fWorkbook.getCreationHelper().createDataFormat().getFormat("dd/MMMM/yyyy"));
            Date currentdate = new Date();
            XSSFSheet fsheet = fWorkbook.getSheetAt(0);
            Double barcodeprintstatus = new Double(1);
            int newindex = 24;
            int printdate = 26;
            int uniqueid = 27;  
            for(int i = 0; i < jTable1.getModel().getRowCount(); i++){
                if(jTable1.getModel().getValueAt(i, newindex).equals("1")){
                    for(int k=1; k < fsheet.getPhysicalNumberOfRows(); k++){
                        XSSFCell cell = fsheet.getRow(k).getCell(uniqueid-1);
                        String uid = cell.getRawValue();
                        if(jTable1.getModel().getValueAt(i, uniqueid).toString().equals(uid)){
                            cell = (fsheet.getRow(i+1)).getCell(newindex-1);
                            cell.setCellType(XSSFCell.CELL_TYPE_NUMERIC);
                            cell.setCellValue(barcodeprintstatus);
                            cell = fsheet.getRow(i+1).getCell(printdate-1);
                            cell.setCellValue(currentdate);
                            cell.setCellStyle(cs);
                        }
                    }
                }
            }

            file.close();
            FileOutputStream fileOutputStream = new FileOutputStream("c:\\sample.xlsx");
            fWorkbook.write(fileOutputStream); // this is taking so much of time. Approximately 1 min. 
            fileOutputStream.close();
        }catch(Exception e){
            e.printStackTrace();
        }

我无法解决这个问题。 fWorkbook.write(fileOutputStream); 就像我上面提到的那样花费了很多时间。请帮忙。有没有其他方法可以保存excel文件?或者我可以为单个列而不是孔工作簿写入部分数据吗?

【问题讨论】:

  • 经过某种反复试验后,我发现 fWorkbook.write(fileOutputStream);正在占用所有这些时间。有什么办法可以减少吗?
  • 您正在尝试保存整张纸。如果您只想保存选定的行,那么您应该只保存选定的行而不是整个工作表。这将减少时间和资源消耗。
  • 我用来编辑的文件只有 325KB,它只包含 12 行 50 列。它大约需要 39 秒。
  • 尝试在 for 循环之前创建一种数据格式和一种单元格样式,并将相同的单元格样式应用于 for 循环内的单元格。

标签: java excel apache-poi xlsx fileoutputstream


【解决方案1】:

FileOutputStream 周围添加BufferedOutputStream

【讨论】:

  • 它的时间仍然和以前一样。
【解决方案2】:

尝试改进代码。

您拨打fSheet.getRow(i+1) 两次。尝试引入一个变量并重用该行而不是获取它。

cell.setCellValue(new Double(1));

在 for 循环之前创建一次 1 double 并重复使用它。

XSSFCellStyle cs = fWorkbook.createCellStyle();
cs.setDataFormat(fWorkbook.getCreationHelper().createDataFormat().getFormat("dd/MMMM/yyyy"));

将单元格样式的创建和初始化移出 for 循环。在循环之前创建它并重复使用。

cell.setCellValue(new Date());

引入一个 Date 变量并只创建一次 Date。再次在 for 循环之前。

【讨论】:

  • 先生,正如您所建议的那样,我这样做了,它仍然花费了相同的时间。经过某种反复试验,我发现 fWorkbook.write(fileOutputStream);正在花费所有时间。有什么办法可以减少吗?
  • 如果用 ByteArrayOutputStream 替换 fileOutputStream 会怎样?它工作得更快吗?
  • 我强烈觉得问题出在 fileOutputStream 的大小上。流的大小越大,写入操作所需的时间就越多。首先检查将是“验证我是否需要保存整个数据?我是否覆盖了相同的值。'。
  • 它仍然无法正常工作,先生,ByteArrayOutputStream 花费的时间与以前相似。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
  • 2019-02-24
  • 1970-01-01
相关资源
最近更新 更多