当前位置: 首页 > 知识库问答 >
问题:

为什么是文件。线路(和类似流)未自动关闭?

江渊
2023-03-14

流状态的javadoc:

流具有基流。方法并实现自动关闭,但几乎所有流实例在使用后实际上都不需要关闭。通常,只有源为IO通道的流(例如由文件行(路径,字符集)返回的流)才需要关闭。大多数流由集合、数组或生成函数支持,不需要特殊的资源管理。(如果流确实需要关闭,则可以在try with resources语句中将其声明为资源。)

因此,在绝大多数情况下,可以在一个线性规划中使用流,如集合。stream()。forEach(系统输出::println) 但用于文件。行和其他资源支持的流,必须使用try with resources语句,否则会泄漏资源。

我觉得这很容易出错,而且没有必要。由于流只能迭代一次,在我看来,不存在输出文件的情况。行不应在迭代后立即关闭,因此实现应在任何终端操作结束时简单地隐式调用close。我错了吗?

共有3个答案

苏运良
2023-03-14

此外,如果你想“一行写”。你可以这样做:

Files.readAllLines(source).stream().forEach(...);

如果您确定需要整个文件并且文件很小,您可以使用它。因为它不是延迟读取。

双志强
2023-03-14

除了@BrianGoetz答案之外,我还有更具体的例子。不要忘记,有转义图案填充方法,如迭代器()。假设您正在这样做:

Iterator<String> iterator = Files.lines(path).iterator();

之后,您可以多次调用hasNext()和next(),然后放弃这个迭代器:迭代器接口完全支持这种使用。无法显式关闭迭代器,这里唯一可以关闭的对象是流。因此,这种方式可以很好地工作:

try(Stream<String> stream = Files.lines(path)) {
    Iterator<String> iterator = stream.iterator();
    // use iterator in any way you want and abandon it at any moment
} // file is correctly closed here.

那博瀚
2023-03-14

是的,这是一个深思熟虑的决定。我们考虑了两种选择。

这里的操作设计原则是“谁获得资源,谁就应该释放资源”。读取EOF时文件不会自动关闭;我们希望文件由打开它们的人显式关闭。由IO资源支持的流是相同的。

幸运的是,该语言为您提供了一种自动化机制:尝试使用资源。由于流实现了自动关闭,您可以执行以下操作:

try (Stream<String> s = Files.lines(...)) {
    s.forEach(...);
}

“自动关闭真的很方便,这样我就可以把它写成一行”的论点很好,但主要是摇尾巴。如果你打开了一个文件或其他资源,你也应该准备好关闭它。有效和一致的资源管理胜过“我想用一行写这个”,我们选择不扭曲设计只是为了保留一行。

 类似资料:
  • 在Java 8中,流类实现了自动关闭。这意味着应该显式关闭流实例。 我理解为什么文件处理程序和数据库连接是可关闭的。但为什么是流呢?

  • 问题内容: 在Java 8中,Stream类实现AutoCloseable。这意味着应显式关闭流实例。 我了解为什么文件处理程序和数据库连接是可关闭的。但是为什么要流? 问题答案: 我认为Stream的当前文档/ javadoc 非常清楚: 流具有BaseStream.close()方法并实现AutoCloseable,但是实际上几乎所有流实例在使用后都不需要关闭。通常,只有源是IO通道的流(例如

  • 此答案指示如何将转换为,同时管理将发生阻塞的位置: 我的问题和评论中的问题一样: 怎么了?为什么你使用一个额外的线程与Promise结合? 答复如下: 它会在你拉线的时候卡住线。如果您已经为这样的未来配置了ExecutionContext,这很好,但是默认的ExecutionContext包含的线程与您拥有的处理器一样多。 我不确定我是否理解这个解释。重申: 有什么问题?在未来内部阻塞不是和手动创

  • 问题内容: 我正在尝试了解Redis的基础知识。Redis是无处不在的一种,它是使事情变得原子化的单线程,但是我无法想象这在内部是如何工作的。 如果它是IO绑定的应用程序(例如Node.js),则我们不设计服务器单线程,该线程在启动IO操作后释放了另一个请求的空间,并在IO操作完成后将数据返回给客户端(提供并发性)。但是在Redis的情况下所有数据都可以在主内存中使用,我们根本就不会做IO操作。那

  • 我正在努力了解Redis的基础知识。其中一个不断出现的地方是,Redis是单线程的,使事物原子化。但我无法想象这是如何在内部工作的。我有以下疑问。 如果是IO绑定的应用程序(如node.js),那么我们不是设计一个服务器单线程吗?线程在发起IO操作后为另一个请求提供空闲,并且在IO操作完成后将数据返回给客户机(提供并发)。但是在redis的情况下,所有的数据都在主存中可用,我们根本不做IO操作。那

  • 目前云SQL限制没有。的活动连接数为 100。https://groups.google.com/forum/#!topic/google-cloud-sql-discuss/F-OS6ucsSWE 这个限制在不久的将来会消失还是增加,而且我们有一个场景,我们将用户交互记录在我们的系统中并将它们存储在数据库中,这可能会达到 sql 连接的最大限制。我们是否应该研究云数据存储,以便数据库可以自动扩展