今天我们真的需要在 close() 之前调用 flush() 吗?

Posted

技术标签:

【中文标题】今天我们真的需要在 close() 之前调用 flush() 吗?【英文标题】:Do we really need to call flush() just before close() today? 【发布时间】:2015-01-08 01:23:37 【问题描述】:

我阅读了这个问题Using flush() before close(),并且接受的答案是这仅意味着您遵循模式。

就像 BufferedWriter#close() 或 FilterOutputStream.#close() 一样,如果所有缓冲的 Stream/Writer 在我们调用 close() 时都会调用它的 flush() 并且如果我们(开发人员和将审查代码的开发人员)都知道那,我们真的还需要这个吗?如果是,是什么原因?

【问题讨论】:

IMO,你没有,但这并不意味着这是一个好主意 :-) 如果你从 Writer 或 OutputStream 实现切换,如果你不刷新那些你可能会遇到意外的行为需要它。你可能会争辩说,有一些无用的 flush()'es 是一个糟糕的 JVM 设计,那么我的回答是“也许”:-) 我们可能研究的另一件事是关于向后兼容性,如果以前版本的 JVM 在没有冲洗()。 您到底在问什么,您所链接的问题未涵盖哪些内容? @jarnbjo,我只需要知道这是否只是一项闲置的工作,除非这只是明确遵守规则? @Leo,您能否在答案中给我们举个例子,如果我们先切换到没有 muanlly flush() 的 OutputStream 会出现什么意外行为? @Jaskey 可能是在其他库中实现的其他类,这些库扩展了 OutputStream 但不遵循这种“关闭时刷新”的合同,这在任何地方都没有说明? :-) 【参考方案1】:

正如 javadoc 所说,您不需要 冲洗自己。 但是,考虑到您的读者和常识,这样做仍然很好。

很少有专家熟记javadoc。 如果不查找它,我无法确定流是否会被刷新, 我可能并不孤单。 看到明确的flush() 调用就非常清楚了, 从而使代码更易于阅读。

此外,方法名称close() 没有任何关于刷新的含义。 它来自Closeable 接口, 自然地,它没有提到冲洗。 如果您在关闭之前不刷新缓冲的输出流, 尽管想冲洗它, 您将依赖可能正确或不正确的假设。 这会削弱您的实施。

您所做的任何假设, 你应该以某种方式传递给未来的维护者。 一种方法是发表评论:

// no need to flush() manually, close() will do it automatically

如果您不留下此评论, 未来的维护者可能也需要查找 javadoc, 如果像我一样,他们没有记住它。 但是,既然现在自己调用它并完成它更容易更好,你为什么还要写这样的评论。

简而言之,在关闭之前先刷新只是遵循良好的逻辑。 无需假设和第二次猜测, 也不需要让你的读者思考。

【讨论】:

还有两件事要明确。1.在close()之前只有缓冲流需要flush() 2.如果我在没有flush()的情况下close(),java.io中的每个流都不会有任何副作用( )。对吗? 1.是的,刷新是一个特定于缓冲输出的概念。另见Flushable 2. java.io 中有很多流。我必须通过所有这些来验证,我只是不明白这样做的意义。另一方面,我又添加了一个刷新的理由,请参阅我更新的答案。【参考方案2】:

对于输出,调用flush() 和close() 很重要,因为缓冲的数据可能会丢失,正如第一个答案here 所解释的那样。如果您的程序输出很小并且您的编写器很快完成,那么根据我的经验,close() 和 flush() 不会有太大区别。

对于输入,我们在系统退出前不调用close()也没关系。

【讨论】:

但是 close() 已经为我们刷新了,所以这是我的问题,为什么我们需要在 close() 之前手动刷新 我以前从来没有这样做过,不知道你为什么会这样做。

以上是关于今天我们真的需要在 close() 之前调用 flush() 吗?的主要内容,如果未能解决你的问题,请参考以下文章

我必须在调用* sql.Tx.Rollback()之前调用* sql.Rows.Close()吗?

为啥即使调用 Close(),等待 ManualResetEvent 的线程也会继续等待?

我们如何跟踪 Javascript 错误?现有的工具真的有效吗?

runtime真的超级好用

方法调用:一看就懂,一问就懵?

python yeild: send, close, throw