在 Scala 中管理可关闭资源移交的最佳方法是什么?

发布于 2024-12-24 23:48:13 字数 997 浏览 0 评论 0原文

我正在查看 scala-arm 库,由 这个答案,它看起来非常适合在大多数情况下管理资源。

不过,乍一看,它似乎无法处理一个上下文:将一个资源“移交”到另一个资源。在使用 I/O 时,这种情况经常出现:

for (fin <- managed(new FileInputStream(file));
     // almost what we want, except see below
     gzip <- managed(new GZIPInputStream(fin));
     src <- managed(Source.fromInputStream(gzip))) {
  /* some fancy code */
}

现在,问题是这样的:如果 gzip 成功创建,那么 it 负责关闭 fin 和 fin 不应关闭(更新:这不太正确 - 双重关闭很好;请参阅已接受的答案)。但另一种方法是:

for (src <- managed(Source.fromInputStream(
              new GZIPInputStream(new FileInputStream(file))))) {
  /* some fancy code */
}

不太正确 - 如果 GZIPInputStream 构造函数中存在(诚然不太可能)错误,则 FileInputStream 不会关闭。 fromInputStream 也是如此。

scala-arm(或其他一些包)是否提供了我尚未找到的安全处理此清理的工具?

I'm looking at the scala-arm library, prompted by this answer, and it looks great for managing resources in most contexts.

There's one context, though, that it doesn't, on first glance, appear to handle: that of "handing off" a resource to another resource. This comes up frequently when working with I/O:

for (fin <- managed(new FileInputStream(file));
     // almost what we want, except see below
     gzip <- managed(new GZIPInputStream(fin));
     src <- managed(Source.fromInputStream(gzip))) {
  /* some fancy code */
}

Now, the problem is this: If gzip is successfully created, then it is responsible for closing fin, and fin should not be closed (update: this isn't quite right - double-close is fine; see accepted answer). The alternative, though:

for (src <- managed(Source.fromInputStream(
              new GZIPInputStream(new FileInputStream(file))))) {
  /* some fancy code */
}

is not quite correct - if there is an (admittedly unlikely) error in the GZIPInputStream constructor, the FileInputStream is not closed. Ditto for fromInputStream.

Does scala-arm (or some other package) provide a facility for handling this cleanup safely that I haven't found yet?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

羁客 2024-12-31 23:48:14

Did a few more minutes of looking, and found that it really doesn't matter. java.io.Closeable stipulates that close()ing an already-closed resource is a no-op. So it's safe to wrap everything in managed and let it double-close. The first code example, therefore, is correct.

请持续率性 2024-12-31 23:48:14

对我来说最好的方法是使用迭代器、枚举器和枚举器的概念,这些概念在函数世界中有其基础。

您可能感兴趣的是具有非常好的实现的 Scalaz 库。

换句话说,使用这些概念是为了让源上的迭代器知道消费器何时结束消费,反之亦然。让缺点知道来源没有什么可提供的。

编辑

这是一个非常清楚的帖子< /a> 关于 iteratee 的用途。查看讨论您的问题的动机参数...无论进展顺利或出错,但在正确的时间关闭资源

The best approach to me is to use the notion of iteratee, enumerator and enumeratee that has its fundation in the functional world.

What you might be interested in is the Scalaz library that have a very good implementation.

In some words those concepts are used in order to have both the iterator on the source knowing when the consummator had ended consumming but also the other way around. Having the cons knowing the source has nothing to provide.

EDIT

Here is a very clear post on what iteratee are for. See the motivation parameter that talks about your problem... closing resources whenever what went well or wrong, but at the right time

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文