从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();
由于
答案 0 :(得分:5)
调用close()
可以根据JVM及其资源执行您想要的操作。
然而,在某些情况下,它可能具有不合需要的效果。例如,如果输入流(最终)是套接字流,则关闭流将关闭套接字,并且可能导致正在发送数据的远程服务器看到网络错误。 (这可能无关紧要,但如果处理不当,您可能会在远程Web服务器的日志文件中看到异常。)
即使它正处于阅读的中间并且没有完成?
是。任何“飞行中”的数据都将被丢弃。
(如果我们讨论的是套接字流,那么远程服务器可能会在接近传播后尝试向套接字写入更多数据时异常。但即使发生这种情况,远程服务器服务器无法知道此端在连接上“拔插”之前实际读取了多少数据。)
此外,缓冲区是否需要以某种方式取消或关闭。
因为它是ByteArrayOutputStream
,所以不需要关闭读取/写入内存缓冲区(字节数组,StringBuffers
)的数据流 2 。 GC可以回收纯粹的内存资源而不会出现任何问题。另外,BufferedInput/OutputStream
不需要关闭如果它包装的流不需要关闭。
1 - 我认为Linux / Unix可以打开套接字,并将其传递给分叉的子进程。但是,父进程和子进程都使用套接字是不切实际的,因为协调它们的使用有困难。此外,您不能在Java进程之间执行此类操作,因为Java Process
API不允许它。
2 - 唯一不存在的假设情况是缓冲区是由共享内存段或内存映射文件支持的NIO Buffer
...垃圾收集器可能无法及时收回。我说假设是因为我认为NIO Buffer
对象没有现成的流包装器。
答案 1 :(得分:1)
close()
是安全的,可以释放资源:http://download.oracle.com/javase/6/docs/api/java/io/InputStream.html#close%28%29
这就是你需要做的就是这一切。它释放所有JVM资源。如果它与套接字关联,则此套接字将被关闭。操作系统(IOW传输层)将简单地丢弃所有缓冲区,即将发送的数据包等。连接的另一端(发送方)可能会看到错误,但无论哪种方式都应该为它做好准备。