在 Scala 中管理可关闭资源移交的最佳方法是什么?
我正在查看 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
又看了几分钟,发现其实没什么关系。
java.io.Closeable
< /a> 规定close()
对已经关闭的资源是无操作。因此,将所有内容包装在托管中并让它双重关闭是安全的。因此,第一个代码示例是正确的。Did a few more minutes of looking, and found that it really doesn't matter.
java.io.Closeable
stipulates thatclose()
ing an already-closed resource is a no-op. So it's safe to wrap everything inmanaged
and let it double-close. The first code example, therefore, is correct.对我来说最好的方法是使用迭代器、枚举器和枚举器的概念,这些概念在函数世界中有其基础。
您可能感兴趣的是具有非常好的实现的 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