ResultSet写入CSV文件为空但遍历有值的问题求助
解决CSV文件为空的问题:分析与修复方案
嘿,我来帮你排查这个问题!你说手动遍历ResultSet能输出内容,但CSVWriter生成的文件是空的,大概率是这几个关键点没处理好:
1. 最可能的原因:CSVWriter未关闭,缓冲区数据未写入磁盘
你创建了CSVWriter后只调用了writeAll,但没有关闭它。文件写入操作通常会先把数据存在内存缓冲区,只有调用close()(或flush())时才会把缓冲区的内容真正写到磁盘上。
修复方法:在写完数据后立刻关闭CSVWriter:
CSVWriter writer = new CSVWriter(new FileWriter("result.csv")); writer.writeAll(rs, true); writer.close(); // 一定要加这行!
2. 数据库资源关闭顺序不当
你的代码里在写完CSV后立刻关闭了Statement和Connection,虽然理论上writeAll已经读取完ResultSet,但有些JDBC驱动在关闭Statement后,会提前释放ResultSet的资源,导致数据没完全写入。建议调整顺序:先关CSVWriter,再关数据库资源。
3. 额外提醒:返回已失效的ResultSet没有意义
你的方法最后返回rs,但此时连接和Statement都已经关闭,这个ResultSet已经处于不可用状态,调用方根本没法用它。如果需要返回查询结果,应该在关闭数据库资源前把ResultSet的数据转换成内存对象(比如List<String[]>)。
修复后的完整代码(顺便优化了资源管理)
我用了try-with-resources语法来自动管理数据库连接和Statement,这样更安全,不用手动关这些资源:
public class DBReader { public List<String[]> executeSQL(SqlContainer sc) { String url = "url"; String user = "user"; String password = "pw"; try (Connection con = DriverManager.getConnection(url, user, password); Statement stmt = con.createStatement()) { System.out.println("=== Started SQL ==="); Class.forName("com.ibm.db2.jcc.DB2Driver"); con.setAutoCommit(false); ResultSet rs = stmt.executeQuery(sc.getSQL()); // 写入CSV并关闭writer CSVWriter writer = new CSVWriter(new FileWriter("result.csv")); writer.writeAll(rs, true); writer.close(); // 如果需要返回数据,把ResultSet转成List(先重置游标) rs.beforeFirst(); List<String[]> resultData = new ArrayList<>(); ResultSetMetaData meta = rs.getMetaData(); int columnCount = meta.getColumnCount(); while (rs.next()) { String[] row = new String[columnCount]; for (int i = 0; i < columnCount; i++) { row[i] = rs.getString(i + 1); } resultData.add(row); } con.commit(); System.out.println(" Finished SQL"); return resultData; } catch (SQLException | ClassNotFoundException | IOException e) { e.printStackTrace(); } return null; } }
另外,如果你用的是OpenCSV这类库,writeAll方法本身会处理ResultSet的游标位置,所以不用手动重置,但如果是自定义的CSVWriter实现,可以试试在writeAll前调用rs.beforeFirst()确保游标在起始位置。
内容的提问来源于stack exchange,提问作者ACupOfBreadTea
相关产品推荐
相关产品推荐

