【问题标题】:Does an OutputStreamWriter without buffering exist?是否存在没有缓冲的 OutputStreamWriter?
【发布时间】:2016-04-23 10:51:08
【问题描述】:

我需要将char 的流转换为bytes 的流,即我需要一个从java.io.Writer 接口到java.io.OutputStream 的适配器,它支持我将拥有的任何有效Charset一个配置参数。

但是,java.io.OutputStreamWriter 类有一个隐藏的秘密:它委托给下面的 sun.nio.cs.StreamEncoder 对象会创建一个 8192 字节 (8KB) 的缓冲区,即使您没有要求它也是如此。

问题是,在OutputStream 端,我插入了一个包装器,该包装器需要计算正在写入的字节数,以便在达到特定数量后立即停止源系统的执行已输出字节数。如果OutputStreamWriter 正在创建一个 8K 缓冲区,我只会收到生成的字节量的通知为时已晚,因为它们只会在缓冲区刷新时到达我的计数器(因此在OutputStreamWriter 缓冲区中已经有超过 8,000 个已生成的字节在等待我)。

所以问题是,Java 运行时中是否有 Writer -> OutputStream 可以无缓冲运行的网桥

我真的非常讨厌自己写这个:(...

注意:每次写入都在OutputStreamWriter 上点击flush() 不是有效的替代方法。这会带来很大的性能损失(StreamEncoder 涉及一个 synchronized 块)。

注意 2:我知道可能有必要在桥上保留一个小的 char 溢出以便计算代理项。并不是说我需要在源系统生成第 n 个字节的那一刻停止执行源系统(这是不可能的,因为字节可以以更大的 byte[] 的形式出现在 write 中称呼)。但是我需要尽快停止它,而等待 8K、2K 甚至 200 字节的缓冲区刷新就太迟了。

【问题讨论】:

  • 可以说它不能完全无缓冲 - 如果您只使用代理对的前半部分调用write,对于大多数编码,作者将拥有 存储它并在写任何东西之前等待第二个字符。
  • 嗯,是的,当然,我明白这一点。但是计算代理对和 8K 缓冲区所需的几个缓冲字符之间存在差异......
  • 我认为那里没有任何“当然” - 我怀疑许多读者会认为您的意思是根本没有缓冲,并且您可能不知道代理对。我建议您编辑问题以澄清这一点。 (例如,如果第一次调用 write 没有停止执行,会不会“为时已晚”?)

标签: java buffer outputstream writer


【解决方案1】:

正如您已经检测到OutputStreamWriter 使用的StreamEncoder 的缓冲区大小为 8KB,并且没有界面可以更改该大小。

但以下 sn-p 为您提供了一种为 OutputStream 获取 Writer 的方法,该 OutputStream 在内部也使用 StreamEncoder 但现在具有用户定义的缓冲区大小:

String charSetName = ...
CharsetEncoder encoder = Charset.forName(charSetName).newEncoder();

OutputStream out = ...
int bufferSize = ...

WritableByteChannel channel = Channels.newChannel(out);
Writer writer = Channels.newWriter(channel, encoder, bufferSize);

【讨论】:

  • 我不能给你足够的分数。它就像一个魅力,非常感谢。我唯一担心的是规范将bufferSize 定义为最小 缓冲区大小。但我看到sun.nio.cs.StreamEncoder 的标准实现只是将其用作固定大小,所以应该这样做。再次感谢。
猜你喜欢
  • 2015-02-16
  • 2011-03-22
  • 2011-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-17
  • 1970-01-01
  • 2017-08-14
相关资源
最近更新 更多