Java检测关闭流

发布于 2024-10-31 12:50:45 字数 344 浏览 3 评论 0原文

我有一个由 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 技术交流群。

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

发布评论

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

评论(5

绮烟 2024-11-07 12:50:45

-1 是流结束时的预期行为。请参阅 InputStream.read ()

从输入流中读取下一个数据字节。值字节以 0 到 255 范围内的 int 返回。如果由于已到达流末尾而没有可用字节,则返回值 -1。此方法将阻塞,直到输入数据可用,检测到流结束,或者抛出异常。

当然,您仍然应该捕获IOException以防止意外事件。

The -1 is the expected behavior at the end of a stream. See InputStream.read():

Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.

You should still catch IOException for unexpected events of course.

魄砕の薆 2024-11-07 12:50:45

我可以安全地假设 -1 仅在流关闭时返回吗?

是的。

您不应该假设这样的事情。您应该阅读 javadoc 并根据指定 API 的行为方式来实现。特别是如果您希望代码健壮(或如您所说的“安全”)。

话虽如此,这或多或少就是javadoc在本例中所说的内容。 (有人可能会质疑 EOF 和“流已关闭”不一定意味着同一件事......并且通过调用 InputStream.close()Socket.close 来关闭流() 本地 会产生不同的效果,但是,这些都与您的用例没有直接关系。)

有没有办法重新创建强行断开连接时发生的IO异常?

不会。首先,通常不会首先抛出任何异常,因此通常没有什么可以“重新创建”。其次,原始异常中的信息(如果有的话)消失了。

我应该发送一个数据包来告诉我的 InputStream 它应该关闭,而不是前面的两种方法吗?

不。最好的方法是测试 read 调用的结果。无论如何,您都需要对其进行测试,因为您不能假设 read(byte[]) 方法(或其他方法)将返回您实际要求的字节数。

我认为在某些情况下抛出应用程序特定的异常是可以的。

但请记住一般原则,即异常不应用于正常的流量控制。


其他答案之一建议创建一个代理 InputStream 来抛出一些异常而不是返回 -1。

海事组织,这是一个坏主意。您最终会得到一个声称是 InputStream 的代理类,但违反了 read 方法的约定。如果代理被传递给需要正确实现的InputStream,这可能会导致麻烦。

其次,InputStream是一个抽象类而不是接口,因此Java的动态代理机制不起作用。 (例如,newProxyInstance 方法需要接口列表,而不是类。)

Am I safe to assume that -1 is only returned when the stream is closed?

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() or Socket.close() locally will have a different effect. However, neither of these are directly relevant to your use-case.)

Is there no way to recreate the IO exception that occurs when the connection is forcefully broken?

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.

Should I send a packet that will tell my InputStream that it should close instead of the previous two methods?

No. The best method is to test the result of the read call. You need to test it anyway, since you cannot assume that the read(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 the read methods. That could lead to trouble if the proxy was passed to something that expected a properly implemented InputStream.

Second, InputStream is an abstract class not an interface, so Java's dynamic proxy mechanism won't work. (For example, the newProxyInstance method requires a list of interfaces, not classes.)

白鸥掠海 2024-11-07 12:50:45

根据InputStream javadoc,read()返回:

数据的下一个字节,如果到达流末尾,则为 -1。

因此,您可以安全地假设这一点,并且最好使用 API 中指定的内容,而不是尝试重新创建异常,因为引发的异常可能与实现相关。

According to the InputStream javadoc, read() returns:

the next byte of data, or -1 if the end of the stream is reached.

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.

做个少女永远怀春 2024-11-07 12:50:45

此外,关闭套接字中的输出流也会关闭套接字本身。

Socket 的 JavaDoc 是这么说的:

公共输出流 getOutputStream()
抛出 IOException 异常

返回此套接字的输出流。

如果此套接字有关联的通道,则结果输出

流委托其所有操作
到频道。如果频道位于
非阻塞模式然后输出
流的写操作将抛出
IllegalBlockingModeException。

关闭返回的OutputStream将关闭关联的套接字。

返回:
    用于将字节写入此套接字的输出流。 
投掷:
    IOException - 如果创建输出流时发生 I/O 错误

或者如果套接字未连接。

不确定这是否是您真正想要做的。

Also, closing the Outputs Stream in a socket closes the socket itself.

This is what the JavaDoc for Socket says:

public OutputStream getOutputStream()
throws IOException

Returns an output stream for this socket.

If this socket has an associated channel then the resulting output

stream delegates all of its operations
to the channel. If the channel is in
non-blocking mode then the output
stream's write operations will throw
an IllegalBlockingModeException.

Closing the returned OutputStream will close the associated socket.

Returns:
    an output stream for writing bytes to this socket. 
Throws:
    IOException - if an I/O error occurs when creating the output stream

or if the socket is not connected.

Not sure that this is what you actually want to do.

动听の歌 2024-11-07 12:50:45

有没有办法重新创建强行断开连接时发生的IO异常?

这个问题我来回答一下。 InputStream只是一个接口。如果您确实希望实现在 EOF 上抛出异常,请提供您自己的小包装器,重写 read() 并在 -1 结果上抛出异常。

最简单(最少编码)的方法是使用动态代理:

InputStream pxy = (InputStream) java.lang.reflect.Proxy.newProxyInstance(
    obj.getClass().getClassLoader(),
    new Class[]{ InputStream.class },
    new ThrowOnEOFProxy(obj));

其中 ThrowOnEOFProxy 将检查方法名称,调用它,如果结果为 -1,则抛出 IOException("EOF")。

Is there no way to recreate the IO exception that occurs when the connection is forcefully broken?

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:

InputStream pxy = (InputStream) java.lang.reflect.Proxy.newProxyInstance(
    obj.getClass().getClassLoader(),
    new Class[]{ InputStream.class },
    new ThrowOnEOFProxy(obj));

where ThrowOnEOFProxy would check the method name, call it and if result is -1, throw IOException("EOF").

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