【问题标题】:Is there a class that exposes an unbuffered readLine method in Java?是否有一个类在 Java 中公开一个无缓冲的 readLine 方法?
【发布时间】:2012-07-04 15:14:33
【问题描述】:

我正在清理我们工作中的一些代码库,其中一个较旧的类用于读取和写入数据。此数据是 US-ASCII 编码字符串和二进制编码原语的混合体。

当前实现使用DataInputStream,但正如您在文档中看到的那样,readLine() 方法已被弃用,因为与将字节转换为字符相关的问题。虽然这个编码问题并没有真正为我们弹出,但弃用是一个问题,因为它已经不适用于某些版本的 OpenJDK 7,并且弃用意味着它可以在将来完全删除。 “官方”替代方案是使用 BufferedReader 中的 readLine,但我们无法使用 DataInputStream 进行完全交换,因为 BufferedReader 无法真正处理二进制编码的原语。

“混合”这两个类的问题在于,当 BufferedReader 从流中缓冲时,它会推进流标记。这意味着从 DataInputStream 对 readDouble() 等方法的后续调用将因 IOExceptions 或 EOFExceptions 而失败,因为流标记的实际位置不是它“应该”在应用程序逻辑上下文中的位置。

我研究了某种 hacky mark()/reset() 策略,但有时流由不支持 mark()/reset() 的 FileInputStream 支持。

除了更改我们的数据协议以将原语写为字符或编写我自己的readLine() 实现(这令人惊讶地不平凡)之外,有没有办法实现这一点?在这一点上,我什至愿意考虑使用外部库。

【问题讨论】:

  • 您听说过 Apache Commons IO 吗? commons.apache.org/io 我几乎已经放弃了内置的 Java SDK IO 类;它们使用起来很复杂,而且通常不能按预期工作。
  • 您可以将底层输入流包装到缓冲流中。然后将BufferedReaderDataInputStream 放在上面。此设置保证您可以使用mark()/reset()
  • 当您说您可以更改数据协议时,这是否意味着您不会被旧方法编码的大量文件所困?
  • @JesseWebb 考虑到我的具体情况,看起来 Apache 库可能会受到相同的限制,但我没有足够的时间来查看它。感谢您的建议!
  • @biziclop 我会调查的。可能会奏效。

标签: java io bufferedreader readline datainputstream


【解决方案1】:

如果当前代码库运行良好并且您唯一的问题是 deprecation 标记,我个人建议从 DataInputStream 类的 readLine 方法复制代码并将其移动到帮助程序/实用程序类. DataInputStreamreadLine 方法不使用大量实例变量,因此只需稍加工作,您就可以正常使用它。示例调用如下所示:Utils.readLine(dataInStream)。这将确保即使删除该方法,您的代码库也不会受到影响。

是的,它很hacky,是的,它看起来有点难看,但它是最快且可能是最安全的替代方案(对剩余代码库的更改最少)。

【讨论】:

  • 这种工作,除了它使用的一个字段很重要; InputStream 是一个实例字段。我最终做的是你和斯蒂芬建议的结合;我将 DataInputStream 子类化并将原始源复制/粘贴为新方法(无法重载,因为 readLine 是最终的)。
  • 好吧,除了调用in.read()(指的是成员in),您还可以在传递给将转发调用底层InputStream 实例。但无论如何,祝你好运。 :)
  • 是的,我想我可以做到这一点,但是子类化会带来更清晰的重构,只需将新类放入并全面重构。
【解决方案2】:

我认为您应该创建一个 DataInputStream 的自定义子类,该子类添加一个类似 readLine 的方法,该方法的行为方式符合您的需要。 (您甚至可以覆盖现有的readLine() 方法。)

是的,一个高效的实现并非易事,但如果您将自定义类堆叠在 BufferedInputStream 之上,您可能会摆脱幼稚的实现。

【讨论】:

  • 这基本上就是我所做的。 readLine 是最终方法,所以我只是复制了源并将其重命名为新方法。巧妙的把戏,我真的很喜欢。
【解决方案3】:

我遇到了类似的问题,我设法通过使用缓冲区大小为 1 的 BufferedReader 来解决它。

因此方法 BufferedReader.readLine() 没有缓冲。

            InputStreamReader inr=(new InputStreamReader( mInputStream(),"ASCII"));
            BufferedReader  mReader=new BufferedReader(inr,1);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-03
    • 2021-10-10
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 2015-08-11
    • 2011-01-11
    • 2023-02-04
    相关资源
    最近更新 更多