Eclipse中POI XSSF生成损坏Workbook问题求助
问题分析与修复方案
核心问题定位
你的Excel文件损坏主要来自POI工作簿复用错误、ResultSet遍历逻辑混乱,以及OneDrive同步的潜在干扰,和SSH隧道本身无关(只是时间点巧合重合)。
具体修复步骤
1. 修复POI工作簿的复用逻辑
POI的Workbook对象在调用write()后,XSSF实现会关闭内部资源包,后续复用该对象写入会导致文件损坏。你当前的流程是"打开文件→删除旧sheet→写入文件→再往同一workbook加新sheet→再次写入",这是错误的。
正确流程:
- 打开文件加载workbook
- 删除旧sheet(如果存在)
- 直接在当前workbook中创建新sheet并填充数据
- 最后只执行一次写入操作,覆盖原文件
修改后的关键代码片段:
try { // 打开文件加载工作簿并及时关闭输入流 FileInputStream inputstream = new FileInputStream("D://OneDrive//ABSEC//ATC_Reporting//expdata.xlsx"); Workbook workbook = WorkbookFactory.create(inputstream); inputstream.close(); // 删除旧sheet(如果存在) XSSFSheet sheet0 = (XSSFSheet) workbook.getSheet("Security_Completions"); if (sheet0 != null) { int index0 = workbook.getSheetIndex(sheet0); workbook.removeSheetAt(index0); } // 连接数据库执行查询 Class.forName("com.mysql.cj.jdbc.Driver"); Connection connection = DriverManager.getConnection( "jdbc:mysql://127.0.0.1:3307/wp_dashort", "dashort", "gt9wkk6r1TPnkgrY"); String mark_complete = "SELECT DISTINCT wpgc.user_id, wpgc.timestamp\r\n" + "FROM wp_grassblade_completions as wpgc \r\n" + " INNER JOIN \r\n" + "wp_usermeta ON wpgc.user_id = wp_usermeta.user_id\r\n" + "WHERE wpgc.user_id NOT IN (SELECT atc_reporting.user_id FROM atc_reporting WHERE course = 'SECURITY') AND wpgc.timestamp BETWEEN (CURRENT_DATE -INTERVAL 30 DAY) AND DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY) AND content_id IN (1575, 642, 1580) \r\n" + "GROUP BY wpgc.user_id\r\n" + "order BY wpgc.timestamp, wp_usermeta.user_id"; PreparedStatement ps = connection.prepareStatement(mark_complete); ResultSet rs = ps.executeQuery(); // 创建新sheet并填充数据 Sheet sheet = workbook.createSheet("Security_Completions"); Row rowhead = sheet.createRow(0); rowhead.createCell(0).setCellValue("Column 1"); rowhead.createCell(1).setCellValue("Column 2"); int rowIndex = 1; // 从第2行开始写入数据 while (rs.next()) { Row row = sheet.createRow(rowIndex++); row.createCell(0).setCellValue(rs.getString(1)); row.createCell(1).setCellValue(StringUtils.left(rs.getString(2), 16)); } // 一次性写入文件并按顺序关闭所有资源 FileOutputStream fileOut = new FileOutputStream("D://OneDrive//ABSEC//ATC_Reporting//expdata.xlsx"); workbook.write(fileOut); fileOut.close(); workbook.close(); rs.close(); ps.close(); connection.close(); System.out.println("Data is saved in excel file."); } catch (Exception ex) { ex.printStackTrace(); // 必须捕获异常,否则中断写入会导致文件损坏 }
2. 修复ResultSet遍历逻辑错误
你原代码中多次调用rs.next(),导致大量数据被跳过,甚至可能因异常中断写入流程:
rs.next(); // 跳过第一行 while (rs.next()) { // ... for (int i = 0; i < 1; ++i) { rs.next(); // 再次跳过一行 } }
上面的修复代码已修正为直接用while(rs.next())遍历所有行,避免数据丢失和异常。
3. 修复字符串比较Bug
if (realm == "Security")是错误的字符串比较方式,应改为:
if ("Security".equals(realm)) { // 常量放前面避免空指针 // ... }
4. 规避OneDrive同步干扰
OneDrive实时同步可能在文件写入时锁定文件导致损坏,可采取:
- 先将文件写入OneDrive外的临时目录,完成后再移动到目标目录
- 暂时关闭OneDrive实时同步,验证是否还出现损坏问题
额外注意事项
- 必须添加异常捕获逻辑,未捕获的异常会导致文件写入不完整
- 所有资源(流、数据库连接、ResultSet等)必须按顺序关闭,避免资源泄漏
内容的提问来源于stack exchange,提问作者David S.
相关产品推荐
相关产品推荐

