Java:浅谈InputStream的close方法
来源:互联网 发布:先导者之爱知重生 编辑:程序博客网 时间:2024/05/23 01:22
原则:最好在任何时候使用InputStream或者OutputStream的时候,在finally中调用close()方法,显式关闭。
一个典型的示例
InputStream in = null;try { in = acquireStream(); ...} finally { if (in != null) in.close();}
fianlly
中的if (in != null) in.close();
也可以用IOUtils.closeQuietly(in);
代替,需要Apache Commons-IO
。
为什么需要调用
InputStream的作用是用来表示从不同数据源产生输入的类,这些数据源包括:
- 字节数组
- String对象
- 文件
- 管道
- 一个由其他种类的流组成的序列,以便我们可以将他们收集合并到一个流内。
- 其他数据源,如Internet连接等
通常不使用close会导致内存泄露,垃圾回收机制会回收,但是最好自己显式关闭,这并不是特别关键。
关键是当InputStream的数据源是文件或者Internet连接的时候。
OutputStream的作用是如FileOutStream,当不调用close的时候,不会将缓存刷入文件中。
InputStream的数据源是文件时
一个InputStream会韩勇一个极小的kernel资源,一个低级的file handle。
当打开文件时,将文件读入到InputStream,会对文件加锁。当你不考虑文件加锁。当你需要读取另一个文件的时候,会打开一个新的InputStream,kernel会分配另一个descriptor(文件流),一直累加,而一个进程的文件描述表是优先,到最后文件描述表将用被用完,所以为了以防万一,最好每次使用完之后都加一个close()
。
测试代码
import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;public class TestInputStream { public static void main(String[] args) {// createTestFile();// testInputStreamWithOutClose();// testInputStreamWithOneFileWithOutClose(); testInputStreamWithClose(); } /** * 创建一万个测试文件 */ public static void createTestFile() { try { for (int i = 0; i < 10000; i++) { FileOutputStream fos = new FileOutputStream(new File( "/Users/shenpengyan/Documents/workspace/Test/testInputStream/Test" + i)); fos.write(i); fos.close(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 用不同文件,不使用close,有"Too many open files in system"报错 */ public static void testInputStreamWithOutClose(){ try { for (int i = 0; i < 10000; i++) { FileInputStream fis = new FileInputStream(new File( "/Users/shenpengyan/Documents/workspace/Test/testInputStream/Test" + i)); System.out.println(fis.toString() + " " + i); // fis.close(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 用同一个文件,不加close,有"Too many open files in system"报错 */ public static void testInputStreamWithOneFileWithOutClose(){ try { for (int i = 0; i < 10000; i++) { FileInputStream fis = new FileInputStream(new File( "/Users/shenpengyan/Documents/workspace/Test/testInputStream/Test1")); System.out.println(fis.toString() + " " + i); // fis.close(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 加close,无"Too many open files in system"报错 */ public static void testInputStreamWithClose(){ try { for (int i = 0; i < 100000; i++) { FileInputStream fis = new FileInputStream(new File( "/Users/shenpengyan/Documents/workspace/Test/testInputStream/Test1")); System.out.println(fis.toString() + " " + i); fis.close(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
当不使用close()方法时,会有报错:Too many open files in system
java.io.FileInputStream@7e349a0e 6079java.io.FileNotFoundException: /Users/shenpengyan/Documents/workspace/Test/testInputStream/Test1 (Too many open files in system) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(FileInputStream.java:120) at TestInputStream.testInputStreamWithOneFileWithOutClose(TestInputStream.java:53) at TestInputStream.main(TestInputStream.java:9)
InputStream的数据源是Internet连接时
这是我实际遇到的情况,实际业务情况为:我需要调用一个图片存储位置,用key读到的图片存到InputStream里面来进行进一步处理,而我忘记了对它进行close,经过测试,处理300左右的请求之后,就不能继续请求了,这是为什么呢?是因为InputStream没有被垃圾回收掉,还一直占用着连接,而图片服务商有连接数限制,导致之后的请求没有返回,被调用的InputStream类如下:
import java.io.FilterInputStream;import java.io.IOException;import java.io.InputStream;import java.net.SocketException;import org.apache.http.client.methods.CloseableHttpResponse;public class ObjectInputStream extends FilterInputStream { private CloseableHttpResponse httpResponse; public ObjectInputStream(InputStream in, CloseableHttpResponse httpResponse) { super(in); this.httpResponse = httpResponse; } public void close() throws IOException { this.httpResponse.close(); try { super.close(); } catch (SocketException e) { // expected from some implementations because the stream is closed } }}
当没有调用close方法的时候,没有调用httpResponse.close();
,连接不会关掉,所以就尴尬了。
理论依据参考:http://stackoverflow.com/questions/26541513/why-is-it-good-to-close-an-inputstream
- Java:浅谈InputStream的close方法
- InputStream的avaliable()方法
- java的InputStream
- java中FileInputStream与InputStream的available()方法的作用
- Java InputStream读取网络响应Response数据的方法!(重要)
- 【java】输入流InputStream的reset()和mark()方法注意事项
- Java基础学习之InputStream的read()方法陷阱
- Java中InputStream和String之间的转换方法
- java.util.Scanner.close()方法
- java在进行流操作的close()方法
- java Socket编程调用ServerSocket的close方法
- java中Scanner类中的close()方法的作用
- 浅谈shutdown()和close()的区别
- 浅谈shutdown()和close()的区别
- InputStream.skip方法的思考
- 慎用InputStream的read()方法
- InputStream.skip方法的思考
- 重复读取InputStream的方法
- Qt 学习 第2节 日志输出和保存
- 素数测试(判断素数)模板
- 贪心算法(5)
- Deep Learning-TensorFlow TFLearn 快速搭建深度学习模型Alxnet
- SolrCloud搜索引擎集群介绍
- Java:浅谈InputStream的close方法
- Y must be a vector or a character array
- javascript表达正则验证公共函数 检查元素,改成统一
- 贪心算法(6)
- MiniGui核心库编译配置选项
- 大疆M100 Onboard SDK Linux系统下飞行示例简记
- 引水入城(dfs的做法)洛谷p1514
- Struts 2中<s:subset>标签的用法
- Oracle快速替换UNDO表空间方法