Java检测关闭流
我有一个由 OutputStream 和 InputStream 组成的通用套接字实现。
完成一些工作后,我将关闭 OutputStream。
完成此操作后,我的 InputStream 的 read() 方法会在无限长的时间内返回 -1,而不是像我预期的那样抛出异常。
我现在不确定最安全的路线,所以我有几个问题:
- 我可以安全地假设 -1 是唯一的吗? 当流关闭时返回?
- 有没有办法重新创建IO 当发生异常时 连接被强行断开?
- 我是否应该发送一个数据包来告诉我的 InputStream 它应该关闭,而不是前面的两种方法?
谢谢!
I have a general socket implementation consisting of an OutputStream and an InputStream.
After I do some work, I am closing the OutputStream.
When this is done, my InputStream's read() method returns -1 for an infinite amount of time, instead of throwing an exception like I had anticipated.
I am now unsure of the safest route to take, so I have a few of questions:
- Am I safe to assume that -1 is only
returned when the stream is closed? - Is there no way to recreate the IO
exception that occurs when the
connection is forcefully broken? - Should I send a packet that will tell my InputStream that it should close instead of the previous two methods?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
-1 是流结束时的预期行为。请参阅
InputStream.read ()
:当然,您仍然应该捕获
IOException
以防止意外事件。The -1 is the expected behavior at the end of a stream. See
InputStream.read()
:You should still catch
IOException
for unexpected events of course.是的。
您不应该假设这样的事情。您应该阅读 javadoc 并根据指定 API 的行为方式来实现。特别是如果您希望代码健壮(或如您所说的“安全”)。
话虽如此,这或多或少就是javadoc在本例中所说的内容。 (有人可能会质疑 EOF 和“流已关闭”不一定意味着同一件事......并且通过调用
InputStream.close()
或Socket.close 来关闭流()
本地 会产生不同的效果,但是,这些都与您的用例没有直接关系。)不会。首先,通常不会首先抛出任何异常,因此通常没有什么可以“重新创建”。其次,原始异常中的信息(如果有的话)消失了。
不。最好的方法是测试
read
调用的结果。无论如何,您都需要对其进行测试,因为您不能假设 read(byte[]) 方法(或其他方法)将返回您实际要求的字节数。我认为在某些情况下抛出应用程序特定的异常是可以的。
但请记住一般原则,即异常不应用于正常的流量控制。
其他答案之一建议创建一个代理 InputStream 来抛出一些异常而不是返回 -1。
海事组织,这是一个坏主意。您最终会得到一个声称是
InputStream
的代理类,但违反了read
方法的约定。如果代理被传递给需要正确实现的InputStream
,这可能会导致麻烦。其次,
InputStream
是一个抽象类
而不是接口
,因此Java的动态代理机制不起作用。 (例如,newProxyInstance
方法需要接口列表,而不是类。)Yes.
You should not assume things like this. You should read the javadoc and implement according how the API is specified to behave. Especially if you want your code to be robust (or "safe" as you put it.)
Having said that, this is more or less what the javadoc says in this case. (One could quibble that EOF and "stream has been closed" don't necessarily mean the same thing ... and that closing the stream by calling
InputStream.close()
orSocket.close()
locally will have a different effect. However, neither of these are directly relevant to your use-case.)No. For a start, no exception is normally thrown in the first place, so there is typically nothing to "recreate". Second the information in the original exception (if there ever was one) is gone.
No. The best method is to test the result of the
read
call. You need to test it anyway, since you cannot assume that theread(byte[])
method (or whatever) will have returned the number of bytes you actually asked for.I suppose that throwing an application specific exception would be OK under some circumstances.
But remember the general principle that exceptions should not be used for normal flow control.
One of the other answers suggests creating a proxy InputStream that throws some exception instead of returning -1.
IMO, that is a bad idea. You end up with a proxy class that claims to be an
InputStream
, but violates the contract of theread
methods. That could lead to trouble if the proxy was passed to something that expected a properly implementedInputStream
.Second,
InputStream
is anabstract class
not aninterface
, so Java's dynamic proxy mechanism won't work. (For example, thenewProxyInstance
method requires a list of interfaces, not classes.)根据
InputStream
javadoc,read()
返回:因此,您可以安全地假设这一点,并且最好使用 API 中指定的内容,而不是尝试重新创建异常,因为引发的异常可能与实现相关。
According to the
InputStream
javadoc,read()
returns:So you are safe to assume that and it's better to use what's specified in the API than try and recreate an exception because exceptions thrown could be implementation-dependent.
此外,关闭套接字中的输出流也会关闭套接字本身。
Socket 的 JavaDoc 是这么说的:
不确定这是否是您真正想要做的。
Also, closing the Outputs Stream in a socket closes the socket itself.
This is what the JavaDoc for Socket says:
Not sure that this is what you actually want to do.
这个问题我来回答一下。 InputStream只是一个接口。如果您确实希望实现在 EOF 上抛出异常,请提供您自己的小包装器,重写 read() 并在 -1 结果上抛出异常。
最简单(最少编码)的方法是使用动态代理:
其中 ThrowOnEOFProxy 将检查方法名称,调用它,如果结果为 -1,则抛出 IOException("EOF")。
I'll answer this one. InputStream is only an interface. If you really want implementation to throw an exception on EOF, provide your own small wrapper, override read()s and throw an exception on -1 result.
The easiest (least coding) way would be to use a Dynamic Proxy:
where ThrowOnEOFProxy would check the method name, call it and if result is -1, throw IOException("EOF").