2013-04-03 50 views
5

我想写入一个套接字。从阅读有关网络IO,在我看来是写的最佳方式是做这样的事情:将BufferedWriter和BufferedOutputStream一起使用是否过分矫枉过正?

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

BufferedWriter将缓冲输入到其建议的OutputStreamWriter,因为它阻止了作家从为每个角色启动编码器。

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

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

编辑:根据JavaDoc上OutputStreamWriter

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

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

​​

回答

1

的的BufferedWriter将缓冲输入到OutputStreamWriter,后者被推荐的,因为它防止了从作家启动每个字符的编码器。

由谁推荐,并在什么情况下? “启动编码器”是什么意思?无论如何,你是否一次向作家写了一个单独的角色? (我们不知道很多关于你如何使用作家......这可能是很重要的。)

的的BufferedOutputStream将随后从Writer缓冲区的字节数,以避免把一个字节的时间可能到网络。

是什么让你觉得它会一次写入一个字节?我认为OutputStreamWriter不太可能一次写入一个字节给底层的作者,除非你真的一次写了一个字符。

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

与以往一样,您应该根据证据来做到这一点......您是否已经做过任何有和没有这些缓冲层的测试?

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

+0

感谢您的回复。从OutputStreamWriter的javadoc中,“write()方法的每次调用都会导致编码转换器在给定字符上被调用。生成的字节在写入底层输出流之前会在缓冲区中累积。这个缓冲区可以被指定,但是默认情况下它对于大多数目的来说足够大了。注意传递给write()方法的字符没有被缓冲。为了获得最高的效率,可以考虑在BufferedWriter中包装一个OutputStreamWriter,以避免频繁的转换器调用“。 OP中的整个报价编辑 – Bruce 2013-04-03 22:24:47

+0

@Bruce:*考虑*,当然。这与推荐*不一样。我会测试它。尽管如此,我仍然很惊讶地发现它在大多数情况下都有显着的不同。 – 2013-04-03 22:26:10

+0

感谢您的有用答复。是的,我应该测试它。它实际上是我为面试做的编程测试的一部分,我想知道那种默认的正确解决方案是什么,或者至少有一个没有明显错误。 – Bruce 2013-04-03 22:31:19

7

Buffered *类的用途是将小写操作合并为一个较大的写操作,从而减少系统调用次数并提高吞吐量。由于BufferedWriter已经将缓冲区中的写入收集起来,然后将缓冲区中的字符转换为另一个缓冲区,并且在一次操作中将该缓冲区写入底层的OutputStream,因此OutputStream已经被大写操作调用。因此,BufferedOutputStream找不到任何组合,并且只是多余的。另外,同样可以适用于BufferedWriter:缓冲只有在写者一次只传递几个字符时才有帮助。如果你知道调用者只写很大的字符串,BufferedWriter将找不到任何可以组合的东西,也是多余的。

+1

感谢您的回复。这澄清了很多。我觉得我觉得这是一种糟糕的形式,没有缓冲,但你说的话有很大的意义。 – Bruce 2013-04-03 22:42:10

1

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

+0

@downvoter你在这里与Javadoc争吵。哪部分是完全错误的? – EJP 2013-07-10 09:30:49

+0

(我不是downvoter!)我认为这是一个完美,简洁的答案!很明显,通过_wrapping_和一个缓冲区,我们确保编码器只有在字符累积时才被触发,并且由于它有一个内部缓冲区,当缓冲区满时它只会触发底层写入。 – SusanW 2016-08-16 18:30:33

相关问题