如何安全地取消InputStream读取?

3

当从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();

谢谢

2个回答

5

调用 close() 可以处理与 JVM 和其资源相关的内容。

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


即使它正在读取并且没有完成?

是的。任何“在途”数据都将被丢弃。

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

(如果我们谈论套接字流,则远程服务器可能会在关闭传播后尝试向套接字写入更多数据时收到异常。但即使发生这种情况,远程服务器也无法知道此端在“断开连接”之前实际读取了多少数据。)

此外,缓冲区是否需要取消或关闭。

由于它是一个 ByteArrayOutputStream,不需要。从 / 写入内存缓冲区(字节数组、StringBuffers)的流不需要关闭2。GC 可以回收纯内存资源而不会出现任何问题。如果包装的流不需要关闭,则 BufferedInput/OutputStream 也不需要关闭。


1 - 我认为 Linux/Unix 可能会打开套接字,并将其传递给分叉的子进程。但是,由于难以协调其使用方式,父进程和子进程都使用套接字是不切实际的。此外,您不能在 Java 进程之间执行此类操作,因为 Java Process API 不允许。

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


这个实现什么也不做。那么,它的意义是什么? - user457015
“它的意思”在你刚引用的那句话之前已经很明显了。InputStream是一个基类,其close()方法的实现已经被指定。你在真正的程序中使用的InputStream子类将会实现close()方法来做一些适当的事情;例如关闭文件描述符、释放内存映射缓冲区等。 - Stephen C

1

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

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


即使它正在读取过程中并且没有完成,也需要关闭吗?这确实是我的问题,无论在调用关闭之前是否需要完成读取。此外,缓冲区是否也需要被取消或关闭?谢谢。 - cottonBallPaws

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接