• java io系列03之 ByteArrayOutputStream的简介,源码分析和示例(包括OutputStream)


    前面学习ByteArrayInputStream,了解了“输入流”。接下来,我们学习与ByteArrayInputStream相对应的输出流,即ByteArrayOutputStream。
    本章,我们会先对ByteArrayOutputStream进行介绍,在了解了它的源码之后,再通过示例来掌握如何使用它。

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_03.html

    ByteArrayOutputStream 介绍

    ByteArrayOutputStream 是字节数组输出流。它继承于OutputStream。
    ByteArrayOutputStream 中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。


    OutputStream 函数列表

    我们来看看ByteArrayOutputStream的父类OutputStream的函数接口

    复制代码
    // 构造函数
    OutputStream()
    
             void    close()
             void    flush()
             void    write(byte[] buffer, int offset, int count)
             void    write(byte[] buffer)
    abstract void    write(int oneByte)
    复制代码

    ByteArrayOutputStream 函数列表

    复制代码
    // 构造函数
    ByteArrayOutputStream()
    ByteArrayOutputStream(int size)
    
                 void    close()
    synchronized void    reset()
                 int     size()
    synchronized byte[]  toByteArray()
                 String  toString(int hibyte)
                 String  toString(String charsetName)
                 String  toString()
    synchronized void    write(byte[] buffer, int offset, int len)
    synchronized void    write(int oneByte)
    synchronized void    writeTo(OutputStream out)
    复制代码

    OutputStream和ByteArrayOutputStream源码分析

    OutputStream是ByteArrayOutputStream的父类,我们先看看OutputStream的源码,然后再学ByteArrayOutputStream的源码。

    1. OutputStream.java源码分析(基于jdk1.7.40)

    复制代码
     1 package java.io;
     2 
     3 public abstract class OutputStream implements Closeable, Flushable {
     4     // 将字节b写入到“输出流”中。
     5     // 它在子类中实现!
     6     public abstract void write(int b) throws IOException;
     7 
     8     // 写入字节数组b到“字节数组输出流”中。
     9     public void write(byte b[]) throws IOException {
    10         write(b, 0, b.length);
    11     }
    12 
    13     // 写入字节数组b到“字节数组输出流”中,并且off是“数组b的起始位置”,len是写入的长度
    14     public void write(byte b[], int off, int len) throws IOException {
    15         if (b == null) {
    16             throw new NullPointerException();
    17         } else if ((off < 0) || (off > b.length) || (len < 0) ||
    18                    ((off + len) > b.length) || ((off + len) < 0)) {
    19             throw new IndexOutOfBoundsException();
    20         } else if (len == 0) {
    21             return;
    22         }
    23         for (int i = 0 ; i < len ; i++) {
    24             write(b[off + i]);
    25         }
    26     }
    27 
    28     public void flush() throws IOException {
    29     }
    30 
    31     public void close() throws IOException {
    32     }
    33 }
    复制代码

    2. ByteArrayOutputStream 源码分析(基于jdk1.7.40)

    复制代码
      1 package java.io;
      2 
      3 import java.util.Arrays;
      4 
      5 public class ByteArrayOutputStream extends OutputStream {
      6 
      7     // 保存“字节数组输出流”数据的数组
      8     protected byte buf[];
      9 
     10     // “字节数组输出流”的计数
     11     protected int count;
     12 
     13     // 构造函数:默认创建的字节数组大小是32。
     14     public ByteArrayOutputStream() {
     15         this(32);
     16     }
     17 
     18     // 构造函数:创建指定数组大小的“字节数组输出流”
     19     public ByteArrayOutputStream(int size) {
     20         if (size < 0) {
     21             throw new IllegalArgumentException("Negative initial size: "
     22                                                + size);
     23         }
     24         buf = new byte[size];
     25     }
     26 
     27     // 确认“容量”。
     28     // 若“实际容量 < minCapacity”,则增加“字节数组输出流”的容量
     29     private void ensureCapacity(int minCapacity) {
     30         // overflow-conscious code
     31         if (minCapacity - buf.length > 0)
     32             grow(minCapacity);
     33     }
     34 
     35     // 增加“容量”。
     36     private void grow(int minCapacity) {
     37         int oldCapacity = buf.length;
     38         // “新容量”的初始化 = “旧容量”x2
     39         int newCapacity = oldCapacity << 1;
     40         // 比较“新容量”和“minCapacity”的大小,并选取其中较大的数为“新的容量”。
     41         if (newCapacity - minCapacity < 0)
     42             newCapacity = minCapacity;
     43         if (newCapacity < 0) {
     44             if (minCapacity < 0) // overflow
     45                 throw new OutOfMemoryError();
     46             newCapacity = Integer.MAX_VALUE;
     47         }
     48         buf = Arrays.copyOf(buf, newCapacity);
     49     }
     50 
     51     // 写入一个字节b到“字节数组输出流”中,并将计数+1
     52     public synchronized void write(int b) {
     53         ensureCapacity(count + 1);
     54         buf[count] = (byte) b;
     55         count += 1;
     56     }
     57 
     58     // 写入字节数组b到“字节数组输出流”中。off是“写入字节数组b的起始位置”,len是写入的长度
     59     public synchronized void write(byte b[], int off, int len) {
     60         if ((off < 0) || (off > b.length) || (len < 0) ||
     61             ((off + len) - b.length > 0)) {
     62             throw new IndexOutOfBoundsException();
     63         }
     64         ensureCapacity(count + len);
     65         System.arraycopy(b, off, buf, count, len);
     66         count += len;
     67     }
     68 
     69     // 写入输出流outb到“字节数组输出流”中。
     70     public synchronized void writeTo(OutputStream out) throws IOException {
     71         out.write(buf, 0, count);
     72     }
     73 
     74     // 重置“字节数组输出流”的计数。
     75     public synchronized void reset() {
     76         count = 0;
     77     }
     78 
     79     // 将“字节数组输出流”转换成字节数组。
     80     public synchronized byte toByteArray()[] {
     81         return Arrays.copyOf(buf, count);
     82     }
     83 
     84     // 返回“字节数组输出流”当前计数值
     85     public synchronized int size() {
     86         return count;
     87     }
     88 
     89     public synchronized String toString() {
     90         return new String(buf, 0, count);
     91     }
     92 
     93     public synchronized String toString(String charsetName)
     94         throws UnsupportedEncodingException
     95     {
     96         return new String(buf, 0, count, charsetName);
     97     }
     98 
     99     @Deprecated
    100     public synchronized String toString(int hibyte) {
    101         return new String(buf, hibyte, 0, count);
    102     }
    103 
    104     public void close() throws IOException {
    105     }
    106 }
    复制代码

    说明
    ByteArrayOutputStream实际上是将字节数据写入到“字节数组”中去。
    (01) 通过ByteArrayOutputStream()创建的“字节数组输出流”对应的字节数组大小是32。
    (02) 通过ByteArrayOutputStream(int size) 创建“字节数组输出流”,它对应的字节数组大小是size。
    (03) write(int oneByte)的作用将int类型的oneByte换成byte类型,然后写入到输出流中。
    (04) write(byte[] buffer, int offset, int len) 是将字节数组buffer写入到输出流中,offset是从buffer中读取数据的起始偏移位置,len是读取的长度。
    (05) writeTo(OutputStream out) 将该“字节数组输出流”的数据全部写入到“输出流out”中。

    示例代码

    关于ByteArrayOutputStream中API的详细用法,参考示例代码(ByteArrayOutputStreamTest.java):

    复制代码
     1 import java.io.IOException;
     2 import java.io.OutputStream;
     3 import java.io.ByteArrayOutputStream;
     4 import java.io.ByteArrayInputStream;
     5 
     6 /**
     7  * ByteArrayOutputStream 测试程序
     8  *
     9  * @author skywang
    10  */
    11 public class ByteArrayOutputStreamTest {
    12 
    13     private static final int LEN = 5;
    14     // 对应英文字母“abcddefghijklmnopqrsttuvwxyz”
    15     private static final byte[] ArrayLetters = {
    16         0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
    17         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
    18     };
    19 
    20     public static void main(String[] args) {
    21         //String tmp = new String(ArrayLetters);
    22         //System.out.println("ArrayLetters="+tmp);
    23 
    24         tesByteArrayOutputStream() ;
    25     }
    26 
    27     /**
    28      * ByteArrayOutputStream的API测试函数
    29      */
    30     private static void tesByteArrayOutputStream() {
    31         // 创建ByteArrayOutputStream字节流
    32         ByteArrayOutputStream baos = new ByteArrayOutputStream();
    33 
    34         // 依次写入“A”、“B”、“C”三个字母。0x41对应A,0x42对应B,0x43对应C。
    35         baos.write(0x41);
    36         baos.write(0x42);
    37         baos.write(0x43);
    38         System.out.printf("baos=%s
    ", baos);
    39 
    40         // 将ArrayLetters数组中从“3”开始的后5个字节写入到baos中。
    41         // 即对应写入“0x64, 0x65, 0x66, 0x67, 0x68”,即“defgh”
    42         baos.write(ArrayLetters, 3, 5);
    43         System.out.printf("baos=%s
    ", baos);
    44 
    45         // 计算长度
    46         int size = baos.size();
    47         System.out.printf("size=%s
    ", size);
    48 
    49         // 转换成byte[]数组
    50         byte[] buf = baos.toByteArray();
    51         String str = new String(buf);
    52         System.out.printf("str=%s
    ", str);
    53 
    54         // 将baos写入到另一个输出流中
    55         try {
    56             ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
    57             baos.writeTo((OutputStream)baos2);
    58             System.out.printf("baos2=%s
    ", baos2);
    59         } catch (IOException e) {
    60             e.printStackTrace();
    61         }
    62     }
    63 }
    复制代码

    运行结果
    baos=ABC
    baos=ABCdefgh
    size=8
    str=ABCdefgh
    baos2=ABCdefgh

  • 相关阅读:
    例题三、简单的分支与循环结构
    第七章例题、心得及问题。
    第六章例题、心得及问题。
    第五章例题、心得及问题。
    第四章例题、心得及问题。
    第三章例题、心得及问题。
    第一章、第二章的心得及问题。
    实验3 分支结构。
    关于我最后一篇不是心得的 心得。
    关于第五章还没看完之后的 心得。
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/3842966.html
Copyright © 2020-2023  润新知