首页 > 编程语言 > 详细

java(jdk1.7) IO系列02之ByteArrayInputStream和ByteArrayOutputStream解析

时间:2017-02-26 22:26:20      阅读:205      评论:0      收藏:0      [点我收藏+]

1.ByteArrayInputStream和ByteArrayOutputStream简介

 ByteArrayInputStream是字节数组输入流,继承InputStream,它里面维护一个缓冲区,也就是一个byte类型的数组,通过一个计数器pos来实现对字节数组的读取。与之相对应的ByteArrayOutputStream是字节数组输出流,继承自OutputStream,它里面也维护一个缓冲区,通过一个计数器count来实现对字节数组的操作。具体实现如下

2.ByteArrayInputStream源码分析

  1 package java.io;
  2 
  3 
  4 public class ByteArrayInputStream extends InputStream {
  5 
  6     //字节缓冲区
  7     protected byte buf[];
  8 
  9     //当前读取字节的位置
 10     protected int pos;
 11 
 12     //标记字节的位置,如果没有标记,则为0
 13     protected int mark = 0;
 14 
 15     //记录字节数组的长度
 16     protected int count;
 17 
 18     //构造函数,初始化相关的参数
 19     public ByteArrayInputStream(byte buf[]) {
 20         this.buf = buf;
 21         this.pos = 0;
 22         this.count = buf.length;
 23     }
 24 
 25     //根据传入的字节数组的起始位置和读取长度的构造函数
 26     public ByteArrayInputStream(byte buf[], int offset, int length) {
 27         this.buf = buf;
 28         this.pos = offset;
 29         this.count = Math.min(offset + length, buf.length);
 30         this.mark = offset;
 31     }
 32 
 33     //返回当前pos位置上字节的值
 34     public synchronized int read() {
 35         //如果当前pos的位置的值超过了byte的最大的值,则和0xff与运算,获取正值
 36         return (pos < count) ? (buf[pos++] & 0xff) : -1;
 37     }
 38 
 39     //把当前字节流里面的数据读取到传入的字节数组中
 40     public synchronized int read(byte b[], int off, int len) {
 41         if (b == null) {
 42             throw new NullPointerException();
 43         } else if (off < 0 || len < 0 || len > b.length - off) {
 44             throw new IndexOutOfBoundsException();
 45         }
 46 
 47         if (pos >= count) {
 48             return -1;
 49         }
 50      //获取当前缓冲的剩余大小
 51         int avail = count - pos;
 52      //如果写入b的长度大于当前缓冲区的大小,则更新写入的长度为当前缓冲区的大小
 53         if (len > avail) {
 54             len = avail;
 55         }
 56         if (len <= 0) {
 57             return 0;
 58         }
 59     //调用native方法把当前缓冲区的内容复制到b中
 60         System.arraycopy(buf, pos, b, off, len);
 61         pos += len;
 62         return len;
 63     }
 64 
 65     //跳过指定的字节大小,如果当前跳过的大小大于剩余的字节的数量,则跳过剩余字节的数量
 66     public synchronized long skip(long n) {
 67         long k = count - pos;
 68         if (n < k) {
 69             k = n < 0 ? 0 : n;
 70         }
 71 
 72         pos += k;
 73         return k;
 74     }
 75 
 76     //返回当前还有多少个字节可读取
 77     public synchronized int available() {
 78         return count - pos;
 79     }
 80 
 81    //是否支持标记
 82     public boolean markSupported() {
 83         return true;
 84     }
 85 
 86     //把字节流的标记位标记到当前流读取的位置,不支持传入的参数
 87     public void mark(int readAheadLimit) {
 88         mark = pos;
 89     }
 90 
 91     //重置当前流到标记的位置开始读取
 92     public synchronized void reset() {
 93         pos = mark;
 94     }
 95 
 96     //该字节流在内存中操作,不需要关闭
 97     public void close() throws IOException {
 98     }
 99 
100 }

 

3.ByteArrayOutputStream源码分析

package java.io;

import java.util.Arrays;


public class ByteArrayOutputStream extends OutputStream {

   //缓冲区
    protected byte buf[];

    //当前缓冲区存储字节的数量
    protected int count;

    //初始化默认的字节流的缓冲大小为32
    public ByteArrayOutputStream() {
        this(32);
    }

   //初始化制定大小的字节流缓冲
    public ByteArrayOutputStream(int size) {
        if (size < 0) {
            throw new IllegalArgumentException("Negative initial size: "
                                               + size);
        }
        buf = new byte[size];
    }

    //对字节流的缓冲扩容
    private void ensureCapacity(int minCapacity) {
        // overflow-conscious code
    //如果当前缓冲区的大小不能继续存放字节,则扩容
if (minCapacity - buf.length > 0) grow(minCapacity); } //字节流缓冲扩容 private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = buf.length; int newCapacity = oldCapacity << 1; //最小扩容为原来的一倍 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity < 0) {//超过Integer的大小,则变为负数 if (minCapacity < 0) // overflow throw new OutOfMemoryError(); newCapacity = Integer.MAX_VALUE; } buf = Arrays.copyOf(buf, newCapacity); } //写入一个字节到字节流数组 public synchronized void write(int b) { ensureCapacity(count + 1); buf[count] = (byte) b; count += 1; } //把传入的字节数组b从off开始写入len的长度到当前字节流数组 public synchronized void write(byte b[], int off, int len) { if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) - b.length > 0)) { throw new IndexOutOfBoundsException(); } ensureCapacity(count + len); System.arraycopy(b, off, buf, count, len); count += len; } //把一个outputStream中存储的数据写入到当前字节流数组 public synchronized void writeTo(OutputStream out) throws IOException { out.write(buf, 0, count); } //重置字节流数组的读取的位置为0 public synchronized void reset() { count = 0; } //把字节流转换成字节数组 public synchronized byte toByteArray()[] { return Arrays.copyOf(buf, count); } //返回当前字节流数组读取的位置 public synchronized int size() { return count; } //根据默认的字节编码来把字节流转换成string public synchronized String toString() { return new String(buf, 0, count); } //根据制定的编码类型转换成字符串 public synchronized String toString(String charsetName) throws UnsupportedEncodingException { return new String(buf, 0, count, charsetName); } @Deprecated public synchronized String toString(int hibyte) { return new String(buf, hibyte, 0 count); } //因为在内存中操作,所以不需要关闭流 public void close() throws IOException { } }

 

4.示例代码


 1 package com.zwc.io.test;
 2 
 3 import java.io.ByteArrayInputStream;
 4 import java.io.ByteArrayOutputStream;
 5 import java.io.IOException;
 6 import java.io.UnsupportedEncodingException;
 7 
 8 public class TestByteArray {
 9     private static final String STRING1 = "好好学习,天天向上,good good study, day day up";
10     public static void main(String[] args) throws Exception {
11         testByteArrayInputStream();
12         System.out.println("=====================");
13         testByteArrayOutputStream();
14         
15     }
16     private static void testByteArrayOutputStream() throws Exception{
17         ByteArrayOutputStream bos = new ByteArrayOutputStream(66);
18         bos.write(STRING1.getBytes("utf-8"));
19         System.out.println(bos.size());
20         System.out.println(bos.toString("utf-8"));
21         byte[] bytes = bos.toByteArray();
22         bos.reset();//重置当前字节输出流的位置到开始位置
23         bos.write(bytes);//重新把字节数组写入到bos中
24         System.out.println(bos.toString("utf-8"));
25         
26     }
27     private static void testByteArrayInputStream()
28             throws UnsupportedEncodingException, IOException {
29         byte[] bytes = STRING1.getBytes("utf-8");
30         ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
31         if(bis.markSupported()) {
32             bis.mark(0);//表示从0的位置开始标记,0实际上没有意义,只会从当前流的cout位置标记,也就是把mark = cout
33         }
34         bis.skip(30);//跳过30个字节
35         byte[] out = new byte[bis.available()];
36         bis.read(out);
37         System.out.println(new String(out, "utf-8"));
38         bis.reset();//回到0标记的位置
39         out = new byte[bis.available()];//重新初始化字节数组
40         bis.read(out);
41         System.out.println(new String(out, "utf-8"));
42     }
43 }

 


 

执行结果:

good good study, day day up
好好学习,天天向上,good good study, day day up
=====================
57
好好学习,天天向上,good good study, day day up
好好学习,天天向上,good good study, day day up

 

java(jdk1.7) IO系列02之ByteArrayInputStream和ByteArrayOutputStream解析

原文:http://www.cnblogs.com/flyinjava/p/6446069.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!