【问题标题】:Closing BufferedReader without closing wrapped stream在不关闭包装流的情况下关闭 BufferedReader
【发布时间】:2026-02-10 10:45:01
【问题描述】:

我目前正在编写一个使用 TCP 套接字与服务器通信的程序。其中一部分需要通过多种方法来回发送信息。但是,我不想为每个请求打开一个新的套接字连接,但我不能保证请求的数量或顺序。为了处理这个问题,我只保留了一个可以重复使用的套接字实例。

但是,为了读取数据,我使用BufferedReader 包装类。因为我复用了同一个socket,所以不能在reader上调用close(),不然我也要关闭socket流。

如果我不想关闭底层流,是否需要在 BufferedReader 上调用 close()?不这样做会导致内存泄漏吗?如果确实需要调用close(),如何在不关闭套接字流的情况下返回内存?

注意:我将在程序终止时关闭底层流,这个问题与此无关。

【问题讨论】:

  • 为什么要为每个请求打开一个新的套接字连接?
  • 'Open up a new socket connection per request'和'reuse the same socket'是相互矛盾的。它是哪一个?下定决心。这些与关闭缓冲阅读器有什么关系?
  • 糟糕!那里的主要错字。我不想为每个请求打开一个新的套接字。已编辑。

标签: java sockets memory-leaks stream


【解决方案1】:

不要关闭BufferedReade更重要的是,不要丢弃BufferedReader;相反,传递它而不是 SocketInputStream

BufferedReader,顾名思义,有一个内部缓冲区。当您从中读取时,它会尝试从底层Reader 填充该缓冲区。这意味着,如果你丢弃它,那些字节就消失了。

现在还有一些未经询问的建议:

  • 您真的要使用Reader 吗?使用DataInputStream/DataOutputStream 可以更好地实现大多数通信协议。使用Reader,您仅限于字符数据(对于BR,仅限于字符数据行)。
  • 你关注编码了吗?在InputStream 之上构造Reader 的正确方法是使用InputStreamReader 的两个参数变体:new InputStreamReader(in, "UTF-8")(您可以使用UTF-8 以外的编码,但have a good reason)。
  • 通常最好使用BufferedInputStream 而不是BufferedReader,因为从流到阅读器的转换可能涉及多次读取。如果你想要readLine(),你可以同时使用。
  • 确保在finally 或try-with-resources 中关闭socket。请参阅this 了解更多信息。

【讨论】:

  • 谢谢,这很有帮助。我有点希望出现一些未经询问的建议。 :) 我已经在使用 InputStreamReader,但你说得对,BufferedInputStream 可能会更好。我会调查的。