美文网首页
java IO-2-IO

java IO-2-IO

作者: 宠辱不惊的咸鱼 | 来源:发表于2019-10-01 09:08 被阅读0次

概述

  • 节点流 <-> 过滤流
  • 输入流 <-> 输出流
  • 字节流 <-> 字符流

装饰模式

构成

  • 抽象构件(Component)
    • InputStream;OutputStream;Reader;Writer
  • 具体构件(ConcreteComponent)
    • ByteArrayInputStream、FileInputStream、PipedInputStream、StringBufferInputStream
    • ByteArrayOutputStream、FileOutputStream、PipedOutputStream、ObjectOutputStream
    • FilterReader、InputStreamReader、CharArrayReader、PipedReader、StringReader
    • BufferedWriter、CharArrayWriter、FilterWriter、OutputStreamWriter、PipedWriter、PrintWriter、StringWriter
  • 抽象装饰(Decorator)
    • FilterInputStream;FilterOutputStream;FilterReader,BufferedReader,InputStreamReader;OutputStreamWriter
  • 具体装饰(ConcreteDecorator)
    • BufferedInputStream、DataInputStream、LineNumberInputStream、PushbackInputStream
    • BufferedOutputStream、DataOutputStream、CheckedOutputStream、CipheOutputSteam
    • LineNumberReader、PushbackReader、FileReader
    • FileWriter

关系

InputStream:被装饰者
FileInputStream:具体被装饰者
FilterInputStream:装饰者
DataInputStream:具体装饰者
abstract class InputStream
FileInputStream extends InputStream
FilterInputStream extends InputStream
DataInputStream extends FilterInputStream implements DataInput

InputStream,节点输入字节流的祖宗,抽象类

read():留给子类实现

public abstract int read() throws IOException;

read(byte b[]):0偏移,塞满数组b

public int read(byte b[]) throws IOException {
    return read(b, 0, b.length);
}

read(byte b[], int off, int len):可以看到,其实就是一个字节一个字节地读取,塞入字节数组b

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;
}

FileInputStream,节点流,继承自InputStream

read():native搞起

public int read() throws IOException {
    return read0();
}
private native int read0() throws IOException;

read(byte b[]):还是native

public int read(byte b[]) throws IOException {
    return readBytes(b, 0, b.length);
}
private native int readBytes(byte b[], int off, int len) throws IOException;

read(byte b[], int off, int len):native

public int read(byte b[], int off, int len) throws IOException {
    return readBytes(b, off, len);
}
private native int readBytes(byte b[], int off, int len) throws IOException;

DataInputStream,过滤流,继承FilterInputStream实现DataInput

read(byte b[]):
这个in是个InputStream的引用,这就是装饰模式;
那么,这个in是什么时候进来的呢,是在DataInputStream的构造方法里进来的

public final int read(byte b[]) throws IOException {
    return in.read(b, 0, b.length);
}

read(byte b[], int off, int len):

public final int read(byte b[], int off, int len) throws IOException {
    return in.read(b, off, len);
}

readInt():

public final int readInt() throws IOException {
    int ch1 = in.read();
    int ch2 = in.read();
    int ch3 = in.read();
    int ch4 = in.read();
    if ((ch1 | ch2 | ch3 | ch4) < 0)
        throw new EOFException();
    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

半透明装饰

首先,说一说透明装饰,或者说理想的装饰模式,那当然是具体装饰者的方法集合,不要超出被装饰者的;这样的话,当我们在业务方法中调用装饰者(往往是接口或者抽象类的一个引用)方法时,就不用担心转型问题;说道这里可能还是很迷糊,那么说个例子,PushbackInputStream。

PushbackInputStream extends FilterInputStream

先看下常规使用装饰模式:

public Client{
    private InputStream in;
    public Client(InputStream in){
        this.in = in;
    }
    ......
    public void read(byte[] b){
        in.read(b, 0, b.length);
    }
}
Socket socket = ...;
byte[] b = ...;
Client client = new Client(socket.getInputStream());
client.read(b);

那么上面这个是ok的,不会有什么问题。
然后,这个时候由于我知道PushbackInputStream这个类,完了我还想用它提供的unread方法。

public Client2{
    private InputStream in;
    public Client2(InputStream in){
        this.in = in;
    }
    ......
    public void unread(int b){
        in.unread(b);
    }
}
Socket socket = ...;
int b = ...;
Client2 client2 = new Client2(new PushbackInputStream(socket.getInputStream()));
client2.unread(b);

那么,这个时候就有问题了,因为unread这个方法是PushbackInputStream(可以认为是个具体装饰者)特有的,InputStream里压根没有。那么Client2的这个unread方法是有问题的,他需要改成这样:

public void unread(int b){
    ((PushbackInputStream)in).unread(b);
}

那么,说到这个半透明装饰,倒不能说是PushbackInputStream不好,毕竟人家提供额外的unread方法,只是我们自己使用的时候需要注意到这个点。

其他典型代码片段

InputStream

public abstract int read() throws IOException;

public int read(byte b[]) throws IOException {
    return read(b, 0, b.length);
}

// 一个字节一个字节读取
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;
}

FileInputStream

FileInputStream extends InputStream

public int read() throws IOException {
    return read0();
}

// native
private native int read0() throws IOException;

public int read(byte b[]) throws IOException {
    return readBytes(b, 0, b.length);
}

/ native
private native int readBytes(byte b[], int off, int len) throws IOException;

public int read(byte b[], int off, int len) throws IOException {
    return readBytes(b, off, len);
}

DataInputStream

DataInputStream extends FilterInputStream implements DataInput

FilterInputStream extends InputStream

// 装饰模式-过滤流的体现,in就是一个InputStream
public final int read(byte b[]) throws IOException {
    return in.read(b, 0, b.length);
}

public final int read(byte b[], int off, int len) throws IOException {
    return in.read(b, off, len);
}

public final int readInt() throws IOException {
    int ch1 = in.read();
    int ch2 = in.read();
    int ch3 = in.read();
    int ch4 = in.read();
    if ((ch1 | ch2 | ch3 | ch4) < 0)
        throw new EOFException();
    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

InputStreamReader

  • StreamDecoder

相关文章

  • java IO-2-IO

    概述 节点流 <-> 过滤流 输入流 <-> 输出流 字节流 <-> 字符流 装饰模式 构成 抽象构件(Compo...

  • Java(JavaEE)学习线路图1

    Java教程 Java 教程Java 简介Java 开发环境配置Java 基础语法Java 对象和类Java 基本...

  • Java学习线路图

    Java教程 Java 教程Java 简介Java 开发环境配置Java 基础语法Java 对象和类Java 基本...

  • 大数据学习线路图

    Java教程 Java 教程Java 简介Java 开发环境配置Java 基础语法Java 对象和类Java 基本...

  • 大数据学习教程

    Java教程 Java 教程Java 简介Java 开发环境配置Java 基础语法Java 对象和类Java 基本...

  • 一篇文章,全面解读Android面试知识点

    Java Java基础 Java集合框架 Java集合——ArrayList Java集合——LinkedList...

  • java学习路线

    javaSE java基础语法 java文件操作 java网络操作 java多线程 java数据库操作 java ...

  • java编程分类

    一、java简介java开发环境配置java基础语法java对象与类java基本数据类型java变量类型java修...

  • Java-01初识Java

    Java的3大版本 Java有三大版本,Java SE, Java ME, Java EE Java SE(Jav...

  • JAVA循环语句(四)9.29

    Java条件 if Java条件if...else Java条件多重if Java条件语句 嵌套if Java条件...

网友评论

      本文标题:java IO-2-IO

      本文链接:https://www.haomeiwen.com/subject/jpdcpctx.html