Guava ByteSreams 常用方法的封装,FileInputStream的兄弟ByteArrayInputSteam,装饰类大兄弟DataOutputStream

ByteArrayInputSteam

JDK解释:一个从字节数组读取的输入流包含一个内部缓冲区包含的字节,可以从流中读取。内部计数器跟踪由读方法提供的下一个字节。Closing a ByteArrayInputStream has no effect. The methods in this class can be called after the stream has been closed without generating an IOException.

ByteArrayInputStream(byte[] buf) 参数buf指定字节数组类型的数据源。 ByteArrayInputStream(byte[] buf, int offset, int lenght) 参数buf指定字节数组类型数据源,参数offset指定从数组中开始读取数据的起始下标位置,lenght指定从数组中读取的字节数。
ByteArrayInputStream类本身采用了适配器设计模式,它把字节数组类型转换为输入流类型,使得程序能够对字节数组进行读操作。这个和FileInputStream差不多,将File转换为字节流。

源码:这里的mark 和 pos和NIO中的有点类似哦!将数据从byte[]转换为Inputstream的包装类?哈哈没有使用过诶,看Guava的源码中才看到这个的使用。

 public class ByteArrayInputStream extends InputStream {

    protected byte buf[];

    protected int pos;

    protected int mark = 0;

    protected int count;

    public ByteArrayInputStream(byte buf[]) {
        this.buf = buf;
        this.pos = 0;
        this.count = buf.length;
    }

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

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

    public synchronized int read(byte b[], int off, int len) {
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        }

        if (pos >= count) {
            return -1;
        }

        int avail = count - pos;
        if (len > avail) {
            len = avail;
        }
        if (len <= 0) {
            return 0;
        }
        System.arraycopy(buf, pos, b, off, len);
        pos += len;
        return len;
    }

    public synchronized long skip(long n) {
        long k = count - pos;
        if (n < k) {
            k = n < 0 ? 0 : n;
        }

        pos += k;
        return k;
    }

    /**
     * Returns the number of remaining bytes that can be read 
     *(or skipped over)
     * from this input stream.
     */
    public synchronized int available() {
        return count - pos;
    }

    public void mark(int readAheadLimit) {
        mark = pos;
    }

    public synchronized void reset() {
        pos = mark;
    }

    /**
     * Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in
     * this class can be called after the stream has been closed without
     * generating an <tt>IOException</tt>.
     */
    public void close() throws IOException {
    }

}

DataOutputStream继承FilterOutputStream(包装类都继承这个)

FilterOutputStream装饰类的核心

 public class FilterOutputStream extends OutputStream {

    protected OutputStream out;
    public FilterOutputStream(OutputStream out) {
        this.out = out;
    }  
    public void write(int b) throws IOException {
        out.write(b);
    }
}

是Java中输入输出流的装饰类
A data output stream lets an application write primitive Java data(原生的Java数据信息到字节流中,提供了一种便利的方式) types to an output stream in a portable way. An application can then use a data input stream to read the data back in.
什么是原生的数据信息呢?int,short,long,double,string等等,因为输入到流中是使用字节为单元的,比如int是4个字节,要使用包装类才方便得到字节数组,那么原生的数据信息就需要自己一个个字节的写入啦,非常的不方便,所以这个的意义也是在于处理这些数据信息哦!

  • writeInt:Writes an int to the underlying output stream as four bytes, high byte first. 这个的处理可以看懂吧,就是简单的处理int的四个字节。

    public final void writeInt(int v) throws IOException {
        out.write((v >>> 24) & 0xFF);
        out.write((v >>> 16) & 0xFF);
        out.write((v >>>  8) & 0xFF);
        out.write((v >>>  0) & 0xFF);
        incCount(4);
    }
  • WriteUTF更加的好玩一些,因为UTF-8的编码方式,有的使用一个字节,有的使用二个字节,有的使用三个字节,所有在DataOutputStream处理中首先是处理String的长度转换为UTF-8需要多少字节,然后在前两位写入数据的长度,后面才开始处理数据信息。这些DataInputStrem都帮我们进行了处理所以使用起来非常的方便。
  • WriteUTF 计算长度
        for (int i = 0; i < strlen; i++) {
            c = str.charAt(i);
            if ((c >= 0x0001) && (c <= 0x007F)) { //1-127
                utflen++;
            } else if (c > 0x07FF) {
                utflen += 3;
            } else {
                utflen += 2;
            }
        }
     // Data Stream写到输入流中
    DataOutputStream dos = new DataOutputStream(new FileOutputStream(
            "datasteam.txt"));

    //按2字节写入,都是写入的低位
    dos.writeBytes("世界"); 

    // 按照Unicode写入 JDK默认的方式
    dos.writeChars("世界"); 

    // 按照UTF-8写入UTF8变长
    //开头2字节是由writeUTF函数写入的长度信息,
    方便readUTF函数读取)
    dos.writeUTF("世界"); 
    dos.flush();
    dos.close();
 ```

 *  writeBytes这里进行了强制转换,肯定会丢失精度的。
 ```
 public final void writeBytes(String s) throws IOException {
        int len = s.length();
        for (int i = 0 ; i < len ; i++) {
            out.write((byte)s.charAt(i));
        }
        incCount(len);
    }
  • writeChars这个就好理解的,两个字节处理。
public final void writeChars(String s) throws IOException {
        int len = s.length();
        for (int i = 0 ; i < len ; i++) {
            int v = s.charAt(i);
            out.write((v >>> 8) & 0xFF);
            out.write((v >>> 0) & 0xFF);
        }
        incCount(len * 2);
    }

Guava ByteStreams 处理字节流信息

提供了一些非常有用的方法,感觉还不错,比如复制字节流到一个另外的一个输出流,将inputStream转换为byte数据
* copy:

public static long copy(InputStream from, OutputStream to) throws IOException {
    checkNotNull(from);
    checkNotNull(to);
    byte[] buf = new byte[8192];
    long total = 0;
    while (true) {
      int r = from.read(buf);
      if (r == -1) {
        break;
      }
      to.write(buf, 0, r);
      total += r;
    }
    return total;
  }
  • 转换为byte数组:是不是很方便!其他的方法不想使用了就这两个非常的可以的!
public static byte[] toByteArray(InputStream in) throws IOException {
    // Presize the ByteArrayOutputStream since we know how large it will need
    // to be, unless that value is less than the default ByteArrayOutputStream
    // size (32).
    ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max(32, in.available()));
    copy(in, out);
    return out.toByteArray();
}

还有个charStream也是和ByteStream差不多
* http://ajoo.iteye.com/blog/737718

总结

对于流信息的认识更加深了一份理解.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值