首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >慢BufferedWriter性能

慢BufferedWriter性能
EN

Stack Overflow用户
提问于 2015-10-20 13:57:03
回答 3查看 1.5K关注 0票数 2

我有一个方法,它将44 MB的数据从一个ResultSet写入一个CSV文件。然而,它大约需要3.5分钟才能完成。对于44 MB的数据来说,这似乎很慢。有人能看到任何东西减慢我的代码吗?:

代码语言:javascript
复制
public static void convertToCSV(final ResultSet rs) throws SQLException, IOException {
    final BufferedWriter fw = new BufferedWriter(new FileWriter(new File("alert.csv")));
    while (rs.next()) {
        fw.write(rs.getString("FIELD1")+",");
        fw.write(rs.getString("FIELD2")+",");
        fw.write(rs.getString("FIELD3")+",");
        final String clobValue = rs.getString("FIELD4");
        if(clobValue==null)
            fw.write("null,");
        else{
            fw.write("\""+clobValue+"\",");
        }
        final Date date = new Date(rs.getLong("FIELD5"));
        final DateFormat format = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
        format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
        final String dateTime[] = format.format(date).split(" ");
        fw.write(dateTime[0]+",");
        fw.write(dateTime[1]);

        fw.write("\n");
    }
    fw.close();
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-10-20 14:12:30

像这样的东西可能会更快

代码语言:javascript
复制
public static void convertToCSV(final ResultSet rs) throws SQLException, IOException {
    final BufferedWriter fw = new BufferedWriter(new FileWriter(new File("alert.csv")));
    final DateFormat format = new SimpleDateFormat("'yyyyMMdd','HH:mm:ss'");
    format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));

    while (rs.next()) {
      StringBuilder sb = new StringBuilder();
      sb.append(rs.getString("FIELD1")).append(',')
        .append(rs.getString("FIELD2")).append(',')
        .append(rs.getString("FIELD3")).append(',');

        final String clobValue = rs.getString("FIELD4");
        if(clobValue==null)
          sb.append("null,");            
        else{
          sb.append('\"').append(clobValue).append('\"').append(',');
        }
        Date date = new Date(rs.getLong("FIELD5"));
        sb.append(format.format(date)).append('\n');
        fw.write(sb.toString());
    }
    fw.close();
}
  1. DateFormat的创建只能在循环之外完成一次。
  2. 使用StringBuilder
  3. 尽可能避免创建临时对象。

您甚至可以重用StringBuilder,方法是将创建移出循环,并在编写完它之后执行setLength(0)

票数 3
EN

Stack Overflow用户

发布于 2015-10-20 14:03:40

这可能取决于JDBC驱动程序、获取策略、磁盘.

但是,您当然可以避免创建这么多临时对象:

  1. DateFormat移出循环。
  2. 避免创建临时字符串rs.getString("FIELD1")+",",而是对编写器执行两次写调用。
  3. 避免分拆操作。
票数 3
EN

Stack Overflow用户

发布于 2015-10-20 14:13:12

您可以在生成StatementResultSet上增加获取大小--这将减少返回数据库获取下一批行所需的次数(默认设置为10 )。它的缺点是它将增加ResultSet的内存占用,因为它将在内存中保存更多的数据。

您的SimpleDatFormat对象是在循环的每次迭代中使用相同的数据创建的--如果将它移出循环,则只实例化它一次。您也可以将setTimeZone(...)语句移出循环之外。

每次使用变量值进行String连接时,都会在内部创建一个新的StringBuilder对象--您可以通过确保从未在循环中进行连接来获得更多的收益。您可以手动创建自己的StringBuilder,将整个行的数据值放入其中,然后将该行写入BufferedWriter一次(可能会牺牲更多的内存),也可以输入更多的write(...)调用以避免进行连接。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33238704

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档