如何安全地取消InputStream读取?

发布于 2024-10-17 09:54:58 字数 572 浏览 5 评论 0原文

当从 InputStream 读取时,是否有一种方法可以在达到一定大小时取消读取并安全地忽略流的其余部分,以确保资源完全释放?

到目前为止,我刚刚读完,但理想情况下我想停止阅读并继续阅读。我该如何安全地进行呢?

这是我到目前为止所得到的:

ByteArrayOutputStream buffer = new ByteArrayOutputStream();

int nRead;
byte[] byteData = new byte[16384];

while ((nRead = inputStream.read(byteData, 0, byteData.length)) != -1){

    if(buffer.size() <= MAX_FILE_SIZE){
        buffer.write(byteData, 0, nRead);
    }

}

if(buffer.size() <= MAX_FILE_SIZE){
    buffer.flush();
    mData = buffer.toByteArray();
}

inputStream.close();

谢谢

When reading from an InputStream, is there a way to cancel the read when it reaches a certain size and ignore the rest of the stream safely ensuring the resources are completely released?

So far, I just finish the read, but ideally I would like to stop reading it and move on. How do I do it safely?

Here is what I have so far:

ByteArrayOutputStream buffer = new ByteArrayOutputStream();

int nRead;
byte[] byteData = new byte[16384];

while ((nRead = inputStream.read(byteData, 0, byteData.length)) != -1){

    if(buffer.size() <= MAX_FILE_SIZE){
        buffer.write(byteData, 0, nRead);
    }

}

if(buffer.size() <= MAX_FILE_SIZE){
    buffer.flush();
    mData = buffer.toByteArray();
}

inputStream.close();

Thanks

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

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

发布评论

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

评论(2

相思故 2024-10-24 09:54:58

调用 close() 可以对 JVM 及其资源执行您想要的操作。

然而,在某些情况下,它可能会产生不良影响。例如,如果输入流(最终)是套接字流,则关闭该流将关闭套接字,并且 take 可能会导致正在发送数据的远程服务器看到网络错误。 (这可能并不重要,但如果处理不当,您很可能会在远程网络服务器的日志文件中看到异常。)


即使它正在阅读中并且没有读完?

是的。任何“正在传输”的数据都将被丢弃。

  • 通过关闭其套接字句柄,该应用程序隐式表示它不再对数据感兴趣。
  • 在正常情况下1,没有其他任何东西具有允许其读取该数据的套接字句柄。
  • 其他任何东西都无法重新连接到套接字。操作系统级别的套接字 API 不支持这一点。
  • 因此,“保留”数据是没有意义的。

(如果我们谈论的是套接字流,那么如果远程服务器在传播关闭后尝试向套接字写入更多数据,则可能会出现异常。但即使发生这种情况,远程服务器也没有在“拔掉插头”连接之前了解此端实际读取了多少数据的方法。)

此外,缓冲区是否也需要以某种方式取消或关闭。

由于它是 ByteArrayOutputStream,所以不需要。从内存缓冲区(字节数组、StringBuffers)读取/写入的流不需要关闭2 。 GC 可以毫无问题地回收纯粹的内存资源。另外,如果BufferedInput/OutputStream 所包装的流不需要关闭,则也不需要关闭。


1 - 我认为 Linux/Unix 可以打开一个套接字,并将其传递给一个分叉的子进程。然而,父进程和子进程同时使用套接字是不切实际的,因为协调它们对套接字的使用很困难。此外,您不能在 Java 进程之间执行此类操作,因为 Java Process API 不允许这样做。

2 - 唯一假设 情况并非如此,当缓冲区是由共享内存段或内存映射文件支持的 NIO Buffer 时……垃圾收集器可能无法及时回收。我说假设是因为我认为 NIO Buffer 对象没有现成的流包装器。

Calling close() does what you want with respect to the JVM and its resources.

However, in some circumstances it could have effects that are undesirable. For instance, if the input stream is (ultimately) a socket stream, then closing the stream closes the socket, and take may cause the remote server that is sending data to see a network error. (This probably doesn't matter, but if it is not handled cleanly, you may well see exceptions in a remote webserver's logfile.)


Even if it was in the middle of being read and doesn't finish?

Yes. Any data that is "in flight" will be thrown away.

  • By closing its socket handle, this application says implicitly that it is no longer interested in the data.
  • Under normal circumstances1, there is nothing else that has the socket handle that allows it to read that data.
  • There is no way for anything else to reconnect to the socket. That is not supported by the socket APIs ... at the operating system level.
  • There is therefore no point in "keeping" the data.

(If we are talking about a socket stream then the remote server might get an exception if it tries to write more data to the socket after the close propagated. But even if that occurs, the remote server has no way of knowing how much data this end actually read before "pulling the plug" on the connection.)

Also, does the buffer need to be somehow cancelled or closed as well.

Since it is a ByteArrayOutputStream, No. Streams that read from / write to in-memory buffers (byte arrays, StringBuffers) don't need to be closed2. The GC can reclaim purely in-memory resources without any issues. Also a BufferedInput/OutputStream doesn't need to be closed if the stream it wraps doesn't need closing.


1 - I think it is possible for a Linux/Unix to open a socket, and pass it to a forked child process. However, it is impractical for both the parent and child processes to both use the socket because of the difficulty coordinating their use of it. Furthermore, you can't do this kind of thing between Java processes because the Java Process API doesn't allow it.

2 - The only hypothetical case where that is not true is when the buffer is a NIO Buffer backed by a shared memory segment or memory-mapped file ... which the garbage collector may be unable to reclaim in a timely fashion. And I say hypothetical because I don't think there are off-the-shelf stream wrappers for NIO Buffer objects.

无妨# 2024-10-24 09:54:58

close() 是安全的并且会释放资源:http://download.oracle.com/javase/6/docs/api/java/io/InputStream.html#close%28%29

这就是你的全部为此需要做的事情。它释放所有 JVM 资源。如果它与套接字关联,则该套接字将被关闭。操作系统(IOW 传输层)将简单地丢弃所有缓冲区、即将到来的数据包等。连接的另一端(发送方)可能会看到错误,但无论哪种方式,都应该为此做好准备。

close() is safe and does release resources: http://download.oracle.com/javase/6/docs/api/java/io/InputStream.html#close%28%29

That is all that you need to do on this end. It releases all JVM resources. If it's associated with a socket, this socket will be closed. Operating system (IOW transport layer) will simply discard all buffers, forthcoming packets etc. The other end of the connection (sender) may see an error, but either way it should be prepared for it.

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