java IO流总结

IO相关类关系图

输入

字节流

image

InputStream
package java.io;

public abstract class InputStream implements Closeable {
    private static final int MAX_SKIP_BUFFER_SIZE = 2048;
    public abstract int read() throws IOException;
    
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }
    
    /* Reads the next byte of data from the input stream. */
    public int read(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        int c = read();
        if (c == -1) { return -1; }
        b[off] = (byte)c;

        int i = 1;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException ee) { }
        return i;
    }
    
    public long skip(long n) throws IOException {
        //...
    }
    public int available() throws IOException {
        return 0;
    }
    public void close() throws IOException {}
    
    //...
}

  InputStream是个抽象类,read()方法未实现,其作用是从输入流中读取一个字节的数据,读多个字节的方法read(byte[] b)与read(byte[] b, int off, int len)都是通过read()一个字节一个字节读出的。
  FileInputStream ByteArrayInputStream StringBufferInputStream PipedInputStream均继承了InputStream,他们的区别仅仅是输入流的不同,有来自文件的,string的,byteArray的,管道的等,这导致它们read()获取下一个字节的方式可能有所不同,但思想结构都是一样的。

public
class StringBufferInputStream extends InputStream {
    protected String buffer;
    public StringBufferInputStream(String s) {
        this.buffer = s;
        count = s.length();
    }
    
    //仔细区分read代码与StringReader中的区别(有没有截取低八位的区别)
    public synchronized int read() {
        return (pos < count) ? (buffer.charAt(pos++) & 0xFF) : -1;
    }
    
    //...
}



  mermaid sequenceDiagramInputStream这个类可以包含多个流,然后一个一个一次读取。
  ObjectInputStream待分析

FilterInputStream

  来看看源码

package java.io;

public
class FilterInputStream extends InputStream {
    protected volatile InputStream in;
    
    protected FilterInputStream(InputStream in) {
        this.in = in;
    }
    public int read() throws IOException {
        return in.read();
    }
    public int read(byte b[], int off, int len) throws IOException {
        return in.read(b, off, len);
    }
    public void close() throws IOException {
        in.close();
    }
    
    //...
}

  FilterInputStream也继承了InputStream, 它有私有变量InputStram in;所有inputStream的方法它都通过调用私有变量对应的方法来实现(看着和代理很像啊)。
  继承FilterInputStream的一个代表类就是BufferedInputStream, 这个类的好处就是通过一个字节数组来缓存读取的内容(当读的内容超过缓存的界限时,就会重新读大段的数据到内存中),这样一次可以缓存多个字节的内容,提高访问效率; 另一个代表类是PushbackInputStream, 这个类独特的作用就是将刚从六中读出的数据塞回数据流中,可以再次读取.

字符流

image

Reader

  Readable接口就一个函数public int read(java.nio.CharBuffer cb) throws IOException;

public abstract class Reader implements Readable, Closeable {

    public int read(java.nio.CharBuffer target) throws IOException {
        int len = target.remaining();
        char[] cbuf = new char[len];
        int n = read(cbuf, 0, len);
        if (n > 0)
            target.put(cbuf, 0, n);
        return n;
    }
    
    public int read(char cbuf[]) throws IOException {
        return read(cbuf, 0, cbuf.length);
    }

    abstract public int read(char cbuf[], int off, int len) throws IOException;
    
    //....
    
    abstract public void close() throws IOException;
}

  Reader和InputStream文件结构是类似的。不同之处再出InputStream一次读一个字节,而Reader一次读取一个字符(2个字节的内容).
  StringReader PipedReader CharArrayReader都继承了Reader,只不过流的来源不同。读取字符的方式不同

public class CharArrayReader extends Reader {
    protected char buf[];
    public CharArrayReader(char buf[]) {
        this.buf = buf;
        this.pos = 0;
        this.count = buf.length;
    }
    
    public int read() throws IOException {
        synchronized (lock) {
            ensureOpen();   //若buf为空报错
            if (pos >= count)
                return -1;
            else
                return buf[pos++];
        }
    }
    
    //...
}

public class StringReader extends Reader {
    private String str;
    private int length;
    public StringReader(String s) {
        this.str = s;
        this.length = s.length();
    }
    
    public int read() throws IOException {
        synchronized (lock) {
            ensureOpen();
            if (next >= length)
                return -1;
            return str.charAt(next++);
        }
    }
    
    //...
}
InputStreamReader(字节流转换为字符流)

  是Reader的子类, 指定编码方式(不指定使用默认值),将字节流转换为字符流。

public class InputStreamReader extends Reader {
    private final StreamDecoder sd;
    
    public InputStreamReader(InputStream in) {
        super(in);
        try {
            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
        } catch (UnsupportedEncodingException e) {
            // The default encoding should always be available
            throw new Error(e);
        }
    }
    public InputStreamReader(InputStream in, String charsetName)
        throws UnsupportedEncodingException
    {
        super(in);
        if (charsetName == null)
            throw new NullPointerException("charsetName");
        sd = StreamDecoder.forInputStreamReader(in, this, charsetName);
    }
    
    public int read() throws IOException {
        return sd.read();
    }
    
    public int read(char cbuf[], int offset, int length) throws IOException {
        return sd.read(cbuf, offset, length);
    }
    
    public void close() throws IOException {
        sd.close();
    }
}

  read方式是由类StreamDecoder完成的.它从InputStream中缓冲byte到内存中,并依据编码方式做解析,返回对应的字符
  StreamDecoder流参考文档
  FileReader继承了InputStreamReader类

public class FileReader extends InputStreamReader {
    public FileReader(String fileName) throws FileNotFoundException {
        super(new FileInputStream(fileName));
    }

    public FileReader(File file) throws FileNotFoundException {
        super(new FileInputStream(file));
    }

    public FileReader(FileDescriptor fd) {
        super(new FileInputStream(fd));
    }
}

  就是将指定文件的FileInputStream流丢给InputStreamReader去完成任务.

输出

字节流

image

outputStream
字符流

image

Writer
OutputStreamWriter

  
是Writer的子类。将输出的字符流变成字节流

延伸

装饰者模式

参考文档

IO类层次关系和各种IO流的用法总结
java io 系列
JAVA与模式-装饰模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值