zoukankan      html  css  js  c++  java
  • Java I/O系列(二)ByteArrayInputStream与ByteArrayOutputStream源码分析及理解

    1. ByteArrayInputStream

    定义


     继承了InputStream,数据源是内置的byte数组buf,那read ()方法的使命(读取一个个字节出来),在ByteArrayInputStream就是简单的通过定向的取buf元素实现的

    核心源码理解


    源码:

    1 public ByteArrayInputStream(byte buf[], int offset, int length) {
    2         this.buf = buf;
    3         this.pos = offset;
    4         this.count = Math.min(offset + length, buf.length);
    5         this.mark = offset;
    6     }

    理解:

    1. 构造ByteArrayInputStream, 直接将外部的byte数组作为内置的buf,作为被读取的数据源

    源码:

     1     // 存放数据的地方
     2     protected byte buf[];
     3 
     4     // 下一个要被读取的位置,即等待读取的位置
     5     protected int pos;
     6 
     7     // 标记pos的位置
     8     protected int mark = 0;
     9 
    10     // 实际能被读取的byte的数量
    11     protected int count;

    理解:

    源码:

     1 public synchronized int read() { 2 return (pos < count) ? (buf[pos++] & 0xff) : -1;} 

    理解:

    1. 该方法是被synchronized修饰的,其它方法也是,故ByteArrayInputStream是线程安全的

    2. byte类型和0xff做与运算,转成byte的无符号类型(0-255),上节也说明过

    源码:

     1 public synchronized int read(byte b[], int off, int len) {
     2         if (b == null) {
     3             throw new NullPointerException();
     4         } else if (off < 0 || len < 0 || len > b.length - off) {
     5             throw new IndexOutOfBoundsException();
     6         }
     7 
     8         if (pos >= count) {
     9             return -1;
    10         }
    11 
    12         int avail = count - pos;
    13         if (len > avail) {
    14             len = avail;
    15         }
    16         if (len <= 0) {
    17             return 0;
    18         }
    19         System.arraycopy(buf, pos, b, off, len);
    20         pos += len;
    21         return len;
    22     }

    理解:

      1. 因为数据源是byte数组,目的源也是byte数组,故直接采用了数组copy的方法,写入到b数组中

    源码:

    1 public synchronized long skip(long n) {
    2         long k = count - pos;
    3         if (n < k) {
    4             k = n < 0 ? 0 : n;
    5         }
    6 
    7         pos += k;
    8         return k;
    9     }

    理解:

      1. 通过调整pos的值,来实现skip操作

    源码:

     1 public void close() throws IOException { 2 } 

    理解:

      1. 空实现,故close后并不会有任何影响,还是可以继续往外读的

     2. ByteArrayOutputStream

    定义


     继承了OutputStream,目的源是内置的byte数组buf,write()方法是一个个字节写入到buf中(其实就是简单到buf[i]=b,这种赋值操作)

    核心源码理解


    源码:

    1 // 目的源,存储数据的地方 
    2 protected byte buf[];
    3 
    4 // buf中实际的byte数(不是buf.length)
    5  protected int count;

     1 public ByteArrayOutputStream() { 2 this(32); 3 } 

    1  public ByteArrayOutputStream(int size) {
    2         if (size < 0) {
    3             throw new IllegalArgumentException("Negative initial size: "
    4                                                + size);
    5         }
    6         buf = new byte[size];
    7     }

     理解:

      1. 默认构造ByteArrayOutputStream的buf长度是32;可以指定存储数据的buf数组的长度

    源码:

    1 public synchronized void write(int b) {
    2         ensureCapacity(count + 1);
    3         buf[count] = (byte) b;
    4         count += 1;
    5     }

    理解:

      1. 重写了InputStream的write(int b) 方法,直接给buf某个元素赋值;

      2. 被synchronized修饰(包括其它方法),因此ByteArrayOutputStream是线程安全的

      3. ensureCapacity,是判断当前的容量和buf.length的大小,如果超过了buf.length,则会对buf进行扩容(申请一个更大的数组,通过Arrays.copyOf方法进行旧元素copy,让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 > 0)) {
    4             throw new IndexOutOfBoundsException();
    5         }
    6         ensureCapacity(count + len);
    7         System.arraycopy(b, off, buf, count, len);
    8         count += len;
    9     }

     理解:

      1. 参数b数组是数据源,待被读取的字节数组,由于目的源是内置的字节数组buf,直接通过数组copy的形式完成写入操作

      2. 与ByteArrayInputStream的read(byte b[], int off, int len)几乎一样,只是内置的buf数组和参数b数组的数据源角色和目的源角色互调下而已

    源码:

     1 public synchronized byte toByteArray()[] { 2 return Arrays.copyOf(buf, count); 3 } 

    public synchronized String toString() {
            return new String(buf, 0, count);
        }
    1 public synchronized String toString(String charsetName)
    2         throws UnsupportedEncodingException
    3     {
    4         return new String(buf, 0, count, charsetName);
    5     }

     理解:

      1. 这三个方法都是取出内置的buf数据,比较容易理解

    源码:

     1 public void close() throws IOException {  } 

    理解:

      1. close后还是可以继续写入的

    3. 总结:

    1. 实现了mark与reset方法,mark方法中让mark=pos,reset时让pos=mark,比较容易理解

    4. 问题:

     1. 欢迎大家提出问题,共同交流学习!

    5. 示例: 

     1     /**
     2      * ByteArrayInputStream的read是从自己内置的buf中读,read的数据源是buf
     3      * ByteArrayOutputStream的write是写入到自己内置的buf中去,write的目的源是buf
     4      */
     5     public static void test1() {
     6         // 对应abcddefghijklmnopqrsttuvwxyz的ASCII码十六进制分别为
     7         byte[] bytes = new byte[] { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
     8                 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
     9         };
    10 
    11         // 0x64, 0x65, 0x66, 0x67, 0x68
    12         ByteArrayInputStream bis = new ByteArrayInputStream(bytes, 3, 5);
    13         ByteArrayOutputStream bos = new ByteArrayOutputStream(); //默认内置的buf长度为32哦
    14         int b = 0;
    15         while((b = bis.read()) != -1) {
    16             System.out.println("ASCII码的十进制: " + b);
    17 
    18             //将读到的字节,再写入到bos中的内置buf中
    19             bos.write(b);
    20         }
    21 
    22         // 虽然close都是空实现,但养成一个关闭资源(比如流,连接)的习惯
    23         try {
    24             bis.close();
    25             bos.close();
    26         } catch (IOException e) {
    27             e.printStackTrace();
    28         }
    29 
    30         System.out.println("bos的内置buf数据: " + bos.toString());
    31     }

    执行:

    1 public static void main(String args[]) {
    2     test1();
    3 }

    结果:

    ASCII码的十进制: 100
    ASCII码的十进制: 101
    ASCII码的十进制: 102
    ASCII码的十进制: 103
    ASCII码的十进制: 104
    bos的内置buf数据: defgh

    6. 参考:

     1. http://www.cnblogs.com/skywang12345/p/io_03.html

  • 相关阅读:
    CF1202F You Are Given Some Letters...
    CF1178E Archaeology
    PTA (Advanced Level) 1005 Spell It Right
    PTA (Advanced Level) 1004 Counting Leaves
    Qt5——从零开始的Hello World教程(Qt Creator)
    PTA (Advanced Level) 1003 Emergency
    PTA (Advanced Level) 1002 A+B for Polynomials
    HDU 1272 小希的迷宫
    FZU 2150 Fire Game
    HihoCoder
  • 原文地址:https://www.cnblogs.com/nolan4954/p/9265170.html
Copyright © 2011-2022 走看看