将BufferedWriter和BufferedOutputStream一起使用是否过度?

时间:2013-04-03 22:12:36

标签: java sockets networking outputstream

我想写一个套接字。从阅读网络IO,在我看来,写入它的最佳方式是做这样的事情:

OutputStream outs=null;
BufferedWriter out=null;
out =
  new BufferedWriter(
    new OutputStreamWriter(new BufferedOutputStream(outs),"UTF-8"));

BufferedWriter会缓冲建议的OutputStreamWriter输入,因为它会阻止编写器为每个字符启动编码器。

然后BufferedOutputStream将缓冲来自Writer的字节,以避免一次将一个字节放到网络上。

它看起来有点像矫枉过正,但它似乎都有帮助吗? 感谢任何帮助......

编辑:来自OutputStreamWriter上的javadoc:

  

每次调用write()方法都会导致在给定字符上调用编码转换器。生成的字节在写入底层输出流之前累积在缓冲区中。可以指定此缓冲区的大小,但默认情况下,它足够大,可用于大多数用途。请注意,传递给write()方法的字符不会被缓冲。

     

为了获得最高效率,请考虑在BufferedWriter中包装OutputStreamWriter,以避免频繁的转换器调用。例如:

Writer out = new BufferedWriter(new OutputStreamWriter(System.out));

3 个答案:

答案 0 :(得分:7)

Buffered *类的目的是将小写操作合并为一个更大的操作,从而减少系统调用次数,并提高吞吐量。

由于BufferedWriter已经在缓冲区中收集写入,然后将缓冲区中的字符转换为另一个缓冲区,并在单个操作中将该缓冲区写入底层的OutputStream,OutputStream已经通过大写操作调用。因此,BufferedOutputStream找不到任何要合并的东西,而且只是多余的。

顺便说一句,同样适用于BufferedWriter:缓冲只有在编写器一次只传递几个字符时才有用。如果你知道调用者只写了很大的字符串,那么BufferedWriter就会发现什么都没有结合起来也是多余的。

答案 1 :(得分:1)

  

BufferedWriter会缓冲outputStreamWriter的输入,建议使用它,因为它会阻止编写器为每个字符启动编码器。

由谁推荐,以及在什么情况下? “启动编码器”是什么意思?你是不是一次向作家写一个角色? (我们不太了解你如何使用作者......这可能很重要。)

  

BufferedOutputStream然后将缓冲来自Writer的字节,以避免一次将一个字节放到网络上。

是什么让你认为它会一次写一个字节?我认为OutputStreamWriter不太可能一次写一个字节到底层编写器,除非你真的一次写一个字符。

此外,我希望网络输出流使用类似Nagle's algorithm的内容来避免发送单字节数据包。

与优化一样,你应该根据证据做到这一点......你有没有这些缓冲层进行任何测试?

编辑:只是为了澄清,我不是说缓冲类是没用的。在某些情况下,他们绝对是正确的方式。我只是说,与所有优化一样,不应盲目使用它们。您应该考虑要优化的内容(处理器使用情况,内存使用情况,网络使用情况等)和度量。这里有许多重要因素 - 其中最重要的是写模式。如果您已经“大块地”编写 - 编写大块字符数据 - 那么缓冲区的影响相对较小。如果你实际上是一次向作家写一个角色,那么它们会更重要。

答案 2 :(得分:1)

是的,它有点矫枉过正。从Javadoc for OutputStreamWriter开始:“write()方法的每次调用都会导致在给定字符上调用编码转换器。结果字节在写入底层输出流之前会累积在缓冲区中。”