Java高效文件写入:字符串连接与对write()的额外调用

时间:2012-02-02 04:15:59

标签: java string performance file-io concatenation

在下面的代码中,哪种情况(1或2)更“高效”?

static final String NEWLINE = System.getProperty("line.separator");
Vector<String> text_vec = ...;
FileWriter file_writer = new FileWriter(path);
BufferedWriter buffered_writer = new BufferedWriter(file_writer);
try {
    for (String text: text_vec) {

        // Case 1: String concatenation
        buffered_writer.write(text + NEWLINE);

        // Case 2: Extra call to write()
        buffered_writer.write(text);
        buffered_writer.write(NEWLINE);
    }
}
finally {
    buffered_writer.close();
}

如果是#1,据我所知,字符串连接由Java编译器通过自动分配StringBuilder对象来处理。由于String值在编译时是未知的,因此无法在“早期”(在编译期间)连接。

所以问题是:哪一个更有效(CPU /内存/挂钟时间)?

我将“有效”的确切定义留给那些回答的人。我不是Java虚拟机的专家。

4 个答案:

答案 0 :(得分:3)

除非你对它进行基准测试并证明你有充分的理由,否则你应该直接写入缓冲区。它是提供一种有效的文件写入方法。

此外,不要忘记在写入缓冲区时刷新缓冲区。

答案 1 :(得分:1)

第二个应该更快,因为它阻止无用的String对象创建,这是因为BufferedWriter写入直接将其输入转换为字节/字符,而不是创建无用的字符串对象。

案例1:

您的代码:

1 time StringBuilder;(通过将字符串附加在一起暗示)

1 time String;(通过将字符串附加在一起暗示)

1 time char[];由缓冲的作家

案例2:

您的代码:

2 time char[];由缓冲的作家


由于最后一个案例产生的对象较少,对象较少,因此这应该更快。

答案 2 :(得分:0)

文件IO比使用JVM中的字符串连接所做的任何操作都要慢几个数量级。无论如何,磁盘都将成为你的瓶颈。

这假设我们不是在谈论SSD,它可能仍然比JVM本身慢。

编辑:显然根据评论没有很好地沟通。 Lemme尝试放大文本框。 OP表示FileWriter。这意味着最终所有数据都必须转到磁盘。磁盘延迟以毫秒为单位,吞吐量以兆字节/秒为单位,通常为10秒,但不是100秒。

内存延迟以纳秒为单位,吞吐量以千兆字节每秒为单位。你的大多数字符串连接发生在那里。这比磁盘快3-6个数量级。

无论您如何缓冲,连接等,最终都会遇到磁盘的吞吐量限制。最重要的是如果你冲洗()并等待它真正完成冲洗到媒体。

缓冲并不意味着蹲下而不是使磁盘IO更有效。是的,你应该在写作时使用缓冲区,大约1k-16k的顺序就足够了。但是,该缓冲区不会更改磁盘的吞吐量。这比字符串连接问题慢几个数量级。

因此。如果您想在写入磁盘时谈论效率,请忘掉如何连接字符串。只需轻松阅读代码即可。

答案 3 :(得分:0)

这一切都通过一个缓冲区,所以应该没什么区别。可能版本2的额外写入速度更快。

但除非你这么多次这样做,否则不重要。