最近在学安卓,写着写着无意间发现这样一个问题,InputStream 对象读过一次之后便为空,一直想不到原因,代码如下:
1 public Bitmap getBitMap(String path) throws Exception{ 2 URL url=new URL(path); 3 HttpURLConnection conn=(HttpURLConnection) url.openConnection(); 4 conn.setConnectTimeout(5000); 5 conn.setRequestMethod("GET"); 6 if(conn.getResponseCode()==200){ 7 InputStream is=conn.getInputStream(); // 在这获取输入流 8 String name=path.substring(path.lastIndexOf("/")+1); 9 File file=new File(Environment.getExternalStorageDirectory(),name); 10 FileOutputStream fos=new FileOutputStream(file); 11 byte [] buffer=new byte[1024]; 12 int len=0; 13 while((len=is.read(buffer))!=-1){ //在这使用过is对象 14 fos.write(buffer,0,len); 15 } 16 return BitmapFactory.decodeStream(is); //返回的bitmap对象为空,很奇怪吧? 17 } 18 return null; 19 } 20
然后去重新看了下java基础知识,发现inputstream类不能读取两次,有人这样比喻,InputStream就类比成一个杯子,杯子里的水就像InputStream里的数据,你把杯子里的水拿出来了,杯子的水就没有了,InputStream也是同样的道理!!所以你想要多次使用InputStream里面的数据,那就保存在一个String里面,这样你想怎么用就怎么用,也没有必要去重复去读InputStream。
深入了解发现InputStream不能读取两次是因为,在InputStream读取的时候,会有一个pos指针,他指示每次读取之后下一次要读取的起始位置,比如说下面的例子
1 @Test 2 public void testByteArrayInputStream() throws Exception { 3 String str = "AAAAACCCCcCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; 4 //ByteArrayInputStream是把一个byte数组转换成一个字节流,读取的内容是从byte数组中读取的 5 ByteArrayInputStream byteInputStream = new ByteArrayInputStream(str.getBytes()); 6 7 //调用这个方法,会影响到下次读取,下次再调用这个方法,读取的起始点会后移5个byte, 8 byteInputStream.read(new byte[5]); 9 10 //ByteArrayOutputStream生成对象的时候,是生成一个100大小的byte的缓冲区,写入的时候,是把内容写入内存中的一个缓冲区 11 ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(100); 12 13 int i =0; 14 byte [] b = new byte[100]; 15 while((i = byteInputStream.read(b))!= -1){ 16 byteOutput.write(b, 0, i); 17 } 18 System.out.println(new String(byteOutput.toByteArray())); 19 }
打印结果是:CCCCcCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
如果要打印出完整的str,去掉第8行 或者 在第九行添加代码,如下
@Test public void testByteArrayInputStream() throws Exception { String str = "AAAAACCCCcCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; //ByteArrayInputStream是把一个byte数组转换成一个字节流,读取的内容是从byte数组中读取的 ByteArrayInputStream byteInputStream = new ByteArrayInputStream(str.getBytes()); //调用这个方法,会影响到下次读取,下次再调用这个方法,读取的起始点会后移5个byte byteInputStream.read(new byte[5]); byteInputStream.reset();//调用reset方法可以使read中的pos指针复位 //ByteArrayOutputStream生成对象的时候,是生成一个100大小的byte的缓冲区,写入的时候,是把内容写入内存中的一个缓冲区 ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(100); int i =0; byte [] b = new byte[100]; while((i = byteInputStream.read(b))!= -1){ byteOutput.write(b, 0, i); } System.out.println(new String(byteOutput.toByteArray())); }
打印结果是:AAAAACCCCcCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
所以可以知道一般我们使用inputStream,需要在一次内处理完所有逻辑。