Java源码学习--InputStream、OutputStream、Reader、Writer

Java源码学习--InputStream、OutputStream、Reader、Writer

Java中的集合类就先告一段落了,之后会学习一下Java中的IO类的源代码。由于Java中IO类都是InputStream、OutputStream、Reader、Writer的实现类,所以这里先来看看这四个类的源代码。

一、InputStream类

该类实现了Closeable几口,不过并没有实现close()方法

InputStream需要认真查看的似乎只有read()、read(byte b[])、read(byte b[], int off, int len)三个方法

1. read()方法

关于该方法,InputStream中规定,该方法返回数据源中下一个字节的int表示,当到达末尾的时候返回-1

在InputStream中该方法是一个抽象方法,等待着子类去实现。

2. read(byte b[], int off, int len)方法

这里跳过read(byte b[])方法的原因是因为该方法的实现就是调用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;
}  

该方法的核心就是:使用read()方法逐个字节地读取数据源中的数据,放入到参数字节数组中,直到数据源的末尾;如果返回值为-1,说明数据源中根本没有数据,否则返回读取的字节个数(一般小于等于len参数)。

二、OutputStream

该类实现了Closeable接口和Flushable接口,前者提供close()方法、后者提供flush()方法,不过OutputStream并没有实现这两个方法。

同InputStream一样,OutputStream方法值得去分析的似乎也只有write(int byte)、write(byte b[])、write(byte b[], int off, int len)

1. write(int byte)

该方法的作用是将参数写入到output stream中去,有一点需要澄清的是,参数是一个int类型,但并不是真的写入一个int类型,只会写入其低8比特位

2. write(byte b[], int off, int len)

同InputStream一样,这里跳过write(byte b[])的原因也是其回调了write(b, 0, b.length)

该方法的作用是将参数b[]中是数据从off开始,len个写入到output stream中去。

public void write(byte b[], int off, int len) throws IOException {
    if (b == null) {
        throw new NullPointerException();
    } else if ((off < 0) || (off > b.length) || (len < 0) ||
               ((off + len) > b.length) || ((off + len) < 0)) {
        throw new IndexOutOfBoundsException();
    } else if (len == 0) {
        return;
    }
    for (int i = 0 ; i < len ; i++) {
        write(b[off + i]);
    }
}  

三、Reader

该类和InputStream相对应,只不过是按字符单位处理数据

Reader实现了Readable接口和Closeable接口,前者是为了适配nio,提供了一个read(java.nio.CharBuffer target)方法。

1. 构造器

Reader较InputStream有一个很大的不同是,其提供了支持同步的lock属性:lock

protected Reader() {
    this.lock = this;
}  

protected Reader(Object lock) {
    if (lock == null) {
        throw new NullPointerException();
    }
    this.lock = lock;
}  

2. read()方法

Reader中的read()方法和read(byte b[], int off, int len)方法的关系同InputStream中是相反的,read()方法是通过后者实现的,而不是同InputStream中那样,后者是调用read()方法来实现数据的读取的。

public int read() throws IOException {
    char cb[] = new char[1];
    if (read(cb, 0, 1) == -1)
        return -1;
    else
        return cb[0];
}  

这样一来对像我这样的强迫症很不适应,每次读取一个数据都需要new 一个char数组来,感觉好亏啊。

3. read(byte b[], int off, int len)

上面提到,该方法的地位等同于InputStream中的read()方法,因此,Reader并没有为该方法提供方法实现,子类需要自己去实现它。

四、Writer

同样,Writer和OutputStream相对应,其实现了Closeable、Flushable两个接口。

1. 构造器

Writer有一个char数组用来缓存:char[] writeBuffer

protected Writer() {
    this.lock = this;
}  

protected Writer(Object lock) {
    if (lock == null) {
        throw new NullPointerException();
    }
    this.lock = lock;
}  

2. write(int c)方法

该方法负责往输出流中写入一个字符的内容,同样,由于参数是一个int类型的数据,这里只会写入参数的低16比特位

public void write(int c) throws IOException {
    synchronized (lock) {
        if (writeBuffer == null){
            writeBuffer = new char[WRITE_BUFFER_SIZE];
        }
        writeBuffer[0] = (char) c;
        write(writeBuffer, 0, 1);
    }
}  

同样可以看到,在Writer中,write()方法是通过write(char[] c, int off, int len)实现的;可以看到在进行写入操作的时候,Writer使用了synchronized关键字,意味着同时只有一个Writer可以进行写入操作

3. write(char[] c, int off, int len)

该方法和Reader中一样,也是供子类来实现。

4. write(String s)和write(String s, int off, int len)方法

由于String的特殊性,其可以看作一个char数组,因此Writer专门为其提供了这两个方法做处理。

public void write(String str) throws IOException {
    write(str, 0, str.length());
}  

public void write(String str, int off, int len) throws IOException {
    synchronized (lock) {
        char cbuf[];
        if (len <= WRITE_BUFFER_SIZE) {
            if (writeBuffer == null) {
                writeBuffer = new char[WRITE_BUFFER_SIZE];
            }
            cbuf = writeBuffer;
        } else {    // Don't permanently allocate very large buffers.
            cbuf = new char[len];
        }
        str.getChars(off, (off + len), cbuf, 0);
        write(cbuf, 0, len);
    }
}  

可见,其本质还是调用的write(char[] c, int off, int len)方法,有一个疑问:这里的synchronized关键字是否是没必要的,这里有不涉及到写入操作,而write方法中本来就有synchronized关键字的啊?

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容

  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,379评论 0 4
  • 五、IO流 1、IO流概述 (1)用来处理设备(硬盘,控制台,内存)间的数据。(2)java中对数据的操作都是通过...
    佘大将军阅读 508评论 0 0
  • 前提 参考资料: 《Java I/O》 -- 这本书没有翻译版,需要自己啃一下。 《Java I/O》这本书主要介...
    zhrowable阅读 1,175评论 0 1
  • 6月9日星期日 晴 这两天早上都领着孙儿去同州湖看国际名校大学生龙舟赛。一是让孙儿放松放松,二是让孙儿长长...
    蓝天白云215阅读 204评论 0 2
  • 独坐书阁望归雁, 白杨村中抚长叹。 残阳余晖散古村, 寒光斜照锁朱门。 我欲乘风登玉宇, 无奈玉兔已飞去。 扣门借...
    乐陵君阅读 159评论 0 1