Java高效的文件写入:字符串浓缩与额外的写入调用()

Java高效的文件写入:字符串浓缩与额外的写入调用(),java,string,performance,file-io,concatenation,Java,String,Performance,File Io,Concatenation,在下面的代码中,哪种情况(1或2)更“有效” 静态最终字符串NEWLINE=System.getProperty(“line.separator”); 向量文本_vec=。。。; FileWriter file\u writer=新的FileWriter(路径); BufferedWriter buffered_writer=新的BufferedWriter(文件_writer); 试一试{ 用于(字符串文本:text\u vec){ //案例1:字符串连接 缓冲_writer.write(文本

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

静态最终字符串NEWLINE=System.getProperty(“line.separator”);
向量文本_vec=。。。;
FileWriter file\u writer=新的FileWriter(路径);
BufferedWriter buffered_writer=新的BufferedWriter(文件_writer);
试一试{
用于(字符串文本:text\u vec){
//案例1:字符串连接
缓冲_writer.write(文本+换行符);
//案例2:对write()的额外调用
缓冲写入器写入(文本);
缓冲写入器写入(换行符);
}
}
最后{
缓冲的_writer.close();
}
在案例#1中,据我所知,字符串连接由Java编译器通过自动分配StringBuilder对象来处理。由于字符串值在编译时是未知的,因此不可能连接“早期”(在编译时)

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


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

文件IO比JVM中的字符串连接要慢几个数量级。无论发生什么情况,磁盘都将成为您的瓶颈

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

编辑:根据评论显然没有很好地沟通。让我在一个较大的文本框中尝试。OP指示一个文件编写器。这意味着最终所有数据都必须进入磁盘。磁盘延迟以毫秒为单位,吞吐量以兆字节/秒为单位,通常为10秒,但不是100秒

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

无论您如何缓冲、连接等,最终都会遇到磁盘的吞吐量限制。尤其是当您刷新()并等待它实际完成对介质的刷新时

缓冲并不意味着占用空间,而是使磁盘IO更高效。是的,写东西时应该使用缓冲区,1k-16k数量级的东西就足够了。但是,该缓冲区不会改变磁盘的吞吐量。这比字符串连接问题要慢几个数量级


所以。如果您想讨论写入磁盘时的效率,请忘记如何连接字符串。只需使代码易于阅读。

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


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

所有内容都通过缓冲区,因此应该没有什么区别。有额外写入的版本2可能更快


但是,除非你做了无数次,否则这并不重要。

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

案例1:

您的代码使:

1次StringBuilder(通过将字符串附加在一起表示)

1时间字符串(通过将字符串附加在一起表示)

1次字符[]由缓冲写入程序执行

案例2:

您的代码使:

2次字符[]由缓冲写入程序执行



由于上一个案例生成的对象更少,对象也更小,因此应该更快。

他不是直接写入文件,而是写入缓冲区。他将写入该文件,无论数据是临时存储在字符串还是缓冲区中。这没什么区别。我第一个评论的要点是,写入缓冲区的速度不会比字符串连接慢多少个数量级。AFAIK,关闭会自动刷新底层流,因此很少需要刷新。
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();
}