• 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

  • 相关阅读:
    C/C++ 构造函数不能是虚函数
    C/C++ STL迭代器失效
    Linux fork函数
    算法和数据结构 限流算法
    数据库 redis底层实现
    C/C++ 虚析构函数
    万物皆可 Serverless 之使用云函数 SCF 快速部署验证码识别接口
    万物皆可 Serverless 之使用云函数 SCF+COS 免费运营微信公众号
    腾讯云云函数 SCF 日志检索最佳实践
    江娱互动「世界争霸」产品迁移至腾讯云云函数的实践
  • 原文地址:https://www.cnblogs.com/yixiu868/p/8144670.html
Copyright © 2020-2023  润新知