ByteArrayInputStream的作用,和BufferedOutputStream 的区别

个人好奇ByteArrayInputStream,到底是有什么用于是百度了一些资料 整合了下,
********这两个类对于要创建临时性文件的程序以及网络数据的传输、数据压缩后的传输等可以提高运行的的效率,可以不用访问磁盘。
同样有StringReader与StringWriter类以字符IO流的方式处理字符串。
流的来源或目的地并不一定是文件,也可以是内存中的一块空间,例如一个字节数组。java.io.ByteArrayInputStream、java.io.ByteArrayOutputStream就是将字节数组当作流输入来源、输出目的地的类
java.io.ByteArrayInputStream将一个字节数组当作流输入的来源,而java.io.ByteArrayOutputStream则可以将一个字节数组当作流输出目的地。
上面的程序就是把字符串转变为字节数组,并作为流输入的来源,用tranform()将字符串中所有的字母都转换为大写的,并将转换后的结果写到ByteArrayOutputStream中。
实例:
ByteArrayInputStream与ByteArrayOutputStream类用于以IO流的方式来完成对字节数组的内容的读写,来支持类似内存虚拟文件或者内存映像文件的功能。

 1  
 2 import java.io.*;  
 3   
 4 public class ByteArrayStreamTest {  
 5     public static void main(String [] args) {  
 6         String str = "abcdef";  
 7           
 8         ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes());  
 9         ByteArrayInputStream out = new ByteArrayOutputStream();  
10           
11         transform(in, out);  
12           
13         byte[] result = out.toByteArray();  
14           
15         System.out.println(out);  
16         System.out.println(new String(result));  
17           
18         transform(System.in, System.out); // 从键盘读,输出到显示器  
19     }  
20       
21     public static void transform(InputStream in, OutputStream out) {  
22         int ch = 0;  
23           
24         try {  
25             while ((ch = in.read()) != -1) {  
26                 int upperChar = Character.toUpperCase((char)ch);  
27                 out.write(upperChar);  
28             } // close while  
29         } catch (Exception e) {  
30             e.printStackTrace();  
31         }  
32     }  
33 }  
View Code

有时候我们需要对同一个InputStream对象使用多次。比如,客户端从服务器获取数据 ,利用HttpURLConnection的getInputStream()方法获得Stream对象,这时既要把数据显示到前台(第一次读取),又想把数据写进文件缓存到本地(第二次读取)。
但第一次读取InputStream对象后,第二次再读取时可能已经到Stream的结尾了(EOFException)或者Stream已经close掉了。
而InputStream对象本身不能复制,因为它没有实现Cloneable接口。此时,可以先把InputStream转化成ByteArrayOutputStream,后面要使用InputStream对象时,再从ByteArrayOutputStream转化回来就好了。代码实现如下:

 1  
 2 
 3 
 4 InputStream input =  httpconn.getInputStream();
 5                 
 6 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 7 byte[] buffer = new byte[1024];
 8 int len;
 9 while ((len = input.read(buffer)) > -1 ) {
10     baos.write(buffer, 0, len);
11 }
12 baos.flush();               
13 
14 
15 InputStream stream1 = new ByteArrayInputStream(baos.toByteArray());
16 
17 
18 //TODO:显示到前台
19 
20 
21 InputStream stream2 = new ByteArrayInputStream(baos.toByteArray());
22 
23 
24 //TODO:本地缓存
View Code

BufferedOutputStream 和 ByteArrayOutputStream的区别

BufferedOutputStream是一个缓冲数据输出流接口, ByteArrayOutputStream则是字节数组输出流接口. 这2个输出流都是我们经常用到的, 它们都是OutputStream的子类,而什么时候选择用它们呢, 这个就要看你运用到什么应用场景下了.
下来先来看下源码吧. 

1.BufferedOutputStream会首先创建一个默认的容器量, capacity = 8192 = 8KB, 每次在写的时候都会去比对capacity是否还够用, 如果不够用的时候, 就flushBuffer(), 把buf中的数据写入对应的outputStream中, 然后将buf清空, 一直这样等到把内容写完. 在这过程中主要起到了一个数据缓冲的功能.

 1 public synchronized void write(byte b[], int off, int len) throws IOException {  
 2       // 在这判断需要写的数据长度是否已经超出容器的长度了,如果超出则直接写到相应的outputStream中,并清空缓冲区  
 3       if (len >= buf.length) {  
 4           flushBuffer();  
 5           out.write(b, off, len);  
 6           return;  
 7       }  
 8       // 判断缓冲区剩余的容量是否还够写入当前len的内容,如果不够则清空缓冲区  
 9       if (len > buf.length - count) {  
10           flushBuffer();  
11       }  
12       // 将要写的数据先放入内存中,等待数据达到了缓冲区的长度后,再写到相应的outputStream中  
13       System.arraycopy(b, off, buf, count, len);  
14       count += len;  
15     }  
View Code

flushBuffer () 这个方法干了些什么呢, 来看看源码 

1 private void flushBuffer() throws IOException {  
2        if (count > 0) {  
3           // 把写入内存中的数据写到构造方法里传入的OutputStream句柄里, 并把容量大小清楚  
4     out.write(buf, 0, count);  
5     count = 0;  
6        }  
7    }  
View Code

这个类最重要的就是这2个方法, 这样节省了大量的内存空间, 合理的分配内存来完成数据输出,当你资源不是那么充沛时, 选择这个类来实现你想要的东西是不是很合适呢?
2.普通的OutputStream, 例如ByteArrayOutputStream也会首先创建一个默认的容器量, capacity = 32 = 32b, 每次在写的时候都会去比对capacity是否还够用, 如果不够用的时候, 就重新创建buf的容量, 一直等到内容写完, 这些数据都会一直处于内存中.

 1 public synchronized void write(byte b[], int off, int len) {  
 2       if ((off < 0) || (off > b.length) || (len < 0) ||  
 3             ((off + len) > b.length) || ((off + len) < 0)) {  
 4           throw new IndexOutOfBoundsException();  
 5       } else if (len == 0) {  
 6           return;  
 7       }  
 8         // 不断对自己的容量进行相加  
 9         int newcount = count + len;  
10         // 如果新的容量大小已经超过了现有的大小时,则重新开辟新的内存区域来保存当前的数据  
11         if (newcount > buf.length) {  
12             buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));  
13         }  
14         System.arraycopy(b, off, buf, count, len);  
15         count = newcount;  
16     }  
View Code

总结 : 当你资源不足够用时,选择BufferedOutputStream是最佳的选择, 当你选择快速完成一个作业时,可以选择ByteArrayOutputStream之类的输出流

转自:http://blog.csdn.net/huijie618/article/details/50233081

posted @ 2017-12-29 15:23  yixiu868  阅读(8673)  评论(0编辑  收藏  举报