You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java CSV写入仅单个输出文件有数据其余空白问题求解

问题根因

文件写入异常的核心原因是IO流关闭顺序完全错误,未触发上层缓冲流的刷盘逻辑:

  • BufferedWriter是带内存缓冲区的包装流,调用write()写入的内容不会立刻落到磁盘,会先暂存在缓冲区中,只有手动调用flush()、缓冲区写满、或者正常调用BufferedWriter自身的close()方法时,内容才会真正写入底层文件。
  • 你的代码只关闭了最底层的FileWriter,从来没有关闭上层的BufferedWriter:每轮循环都会新建一个BufferedWriter实例,进入下一轮循环时,上一轮的BufferedWriter引用被新值覆盖,实例变成游离状态,缓冲区里暂存的内容既没有刷盘,也没有正常关闭,直接随对象回收丢失,对应前两个公司的文件自然是空的。
  • 最后一轮循环创建的BufferedWriter在循环结束后没有引用覆盖,程序运行到末尾退出时,部分JVM实现会在终止流程中强制把未释放的流缓冲区内容刷到磁盘,所以只有最后处理的公司对应文件有内容——这也能解释你移除C的查询后,A和B仍然只有最后一个有内容、前一个空白的现象。
  • 你注释掉的fstream.flush()完全无效:flush操作必须作用在最上层的缓冲流上才会把整个链路的缓冲区内容刷下去,调用底层FileWriter的flush碰不到BufferedWriter里暂存的数据。
修复方案

优先推荐用Java 7及以上版本支持的try-with-resources语法自动管理资源,流会按照「先开后关、上层先关」的正确顺序自动关闭,自动触发刷盘,不会出现资源泄漏或者内容丢失的问题:

while (rsGroups.next()) {
    String groupcode = rsGroups.getString("GroupCode");
    String groupname = rsGroups.getString("groupname");
    String sqlGetComms = "Select companyname from companies where groupcode ='" + groupcode + "'";
    System.out.println(sqlGetComms);
    ResultSet rs2 = st.executeQuery(sqlGetComms);
    // 结果集、输出流全部放入try括号自动管理,不需要手动写close
    try (rs2;
         FileWriter fstream = new FileWriter("C:\\temp\\" + groupname + "comms.csv");
         BufferedWriter out = new BufferedWriter(fstream)) {
        while (rs2.next()) { 
            out.write(rs2.getString("CompanyName"));
            System.out.println(rs2.getString("companyname"));
            out.newLine();
        }
    } catch (IOException | SQLException e) {
        // 按自身业务需求处理异常,比如打印错误日志、返回失败响应
        e.printStackTrace();
    }
}
System.out.println("done");

如果使用的是Java 6及更早版本,就手动在finally块里按顺序释放资源,注意一定要先关最上层的BufferedWriter,再关底层的FileWriter,最后关数据库结果集:

while (rsGroups.next()) {
    String groupcode = rsGroups.getString("GroupCode");
    String groupname = rsGroups.getString("groupname");
    String sqlGetComms = "Select companyname from companies where groupcode ='" + groupcode + "'";
    System.out.println(sqlGetComms);
    ResultSet rs2 = null;
    FileWriter fstream = null;
    BufferedWriter out = null;
    try {
        rs2 = st.executeQuery(sqlGetComms);
        fstream = new FileWriter("C:\\temp\\" + groupname + "comms.csv");
        out = new BufferedWriter(fstream);
        while (rs2.next()) { 
            out.write(rs2.getString("CompanyName"));
            System.out.println(rs2.getString("companyname"));
            out.newLine();
        }
    } catch (IOException | SQLException e) {
        e.printStackTrace();
    } finally {
        // 逐个判空关闭,避免空指针
        try {if (out != null) out.close();} catch (IOException e) {e.printStackTrace();}
        try {if (fstream != null) fstream.close();} catch (IOException e) {e.printStackTrace();}
        try {if (rs2 != null) rs2.close();} catch (SQLException e) {e.printStackTrace();}
    }
}
System.out.println("done");
额外注意点
  • 你当前直接拼接SQL参数的写法存在SQL注入风险,后续可以改成PreparedStatement用占位符传参,既安全也能避免特殊字符转义导致的查询异常。
  • 所有IO流、数据库连接这类需要释放的资源,必须保证在任何代码执行分支下都能被正确关闭,否则很容易出现文件锁残留、内容丢失、连接占满的问题。

内容的提问来源于stack exchange,提问作者cjingeorgia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 06:45:41