学习笔记之java.io包中的字节流(上)—— 基本的InputStream和OutputStream
2017-02-11 19:18
483 查看
先看下类的声明:
可见此二者都是抽象类,而非接口。也就是说除了分别满足java.io.Closeable和java.io.Flushable,提供了close()和flush()方法的默认实现外,还给出了其它实现,像InputStream就提供了skip()方法实现等。
我们更关心的是InputStream中的几个read()方法和OutputStream的几个write()方法。而实际上最核心的read()和write()方法,InputStream和OutputStream并未给出直接实现,这正是InputStream和OutputStream抽象的地方,我们来看下。
InputStream的read()方法:
public abstract int read() throws IOException; 核心read()方法,留给子类实现。
public int read(byte b[])
public int read(byte b[], int off, int len)
后两者是调用第一个方法读特定长度的数据放入byte数组中。
OutputStream的write()方法:
public abstract void write(int b) throws IOException; 核心write()方法,留给子类实现。
public void write(byte b[])
public void write(byte b[], int off, int len)
和read()类似,把字节数组中的特定数据挨个调用第一个write()方法写出。
再说read()和wirte()实现,那么就要看一下InputStream和OutputStream的子类。我们先来看看InputStream和OutputStream的直接子类。
在java.io中InputStream的直接子类有:
java.io.ByteArrayInputStream
java.io.FileInputStream
java.io.FilterInputStream
java.io.ObjectInputStream
java.io.PipedInputStream
java.io.SequenceInputStream
java.io.StringBufferInputStream
而java.io中OutputStream的直接子类有:
java.io.ByteArrayOutputStream
java.io.FileOutputStream
java.io.FilterOutputStream
java.io.ObjectOutputStream
java.io.PipedOutputStream
这些当中,FileInputStream和FileOutputStream是与外部IO直接有关系的,而FilterInputStream和FilterOutputStream是“装饰者”设计实现的基类,其它各类都是特定场景下InputStream和OutputStream的实现,我们来具体看看。
1. FileInputStream/FileOutputStream
顾名思义,是文件的输入流和输出流。文件存在于哪里呢?通常存在于外部设备上,这个是这些实现类中比较特殊的。我们如果做过C语言开发,知道我们通常会open操作系统中的文件,并保留其文件描述符fd。其实,在Java中我们也有类似的东西。首先,就有fd属性,它是FileDescriptor类,和C等底层语言中一样,这实际上是对底层文件的一个描述符,和底层文件进行交互的时候少不了它。实际上在FileInputStream/FileOutputStream对象构造方法中,我们初始化了FileDescriptor的fd对象,并调用了open()方法。
遗憾的是,像open()、read()、write()、skip()、available()这些FileInputStream/FileOutputStream中的具体操作方法,在(Sun)JDK中都冠以native,即本地实现,这样做的好处就是上层开发使用者不必关心,统统交由JVM等底层实现进行处理,实现了平台无关性。
在FileInputStream还有这样几个属性:
private final FileDescriptor fd;
private FileChannel channel = null; JDK1.4之后为了支持NIO的Channel操作
private final Object closeLock = new Object(); 关闭时的并发同步锁
private volatile boolean closed = false; 关闭标志
private static final ThreadLocal<Boolean> runningFinalize =
new ThreadLocal<>(); finalize是否运行的标志
此外,再简要看下FileInputStream构造方法的一个具体实现:
其它重载要么是调用了这个方法,要么实质上是一致的。FileOutputStream也是类似,出了open()调用的时候有一个append属性参数,标志是否为文件追加。
2. ByteArrayInputStream/ByteArrayOutputStream
名称也很直接,实际上就是字节数组,在构造类对象的时候给出一个byte数组。对于ByteArrayInputStream来说,这个byte数组就是读取的源头,而ByteArrayOutputStream则是write()的目的地。
此外,构造方法中还可以指定这个byte数组的有效起点和长度。
而对于ByteArrayOutputStream,给出byte数组长度参数即可。甚至还有默认实现,长度32。
3. PipedInputStream/PipedOutputStream
从名字理解也没错,就是管道输入输出(字节)流。它们的存在需要彼此,即PipedInputStream对象和PipedOutputStream对象只有互相存在才真正有意义,当然可以先构建后连接(connect)。
总体来说就是PipedInputStream维护了一个PipedOutputStream对象的属性,而PipedOutputStream也维护了一个PipedInputStream对象属性。而PipedInputStream额外维护了一个缓冲区数组。当PipedOutputStream执行write()的时候,如果PipedInputStream对象未就绪,会发生一个异常。就绪情况下会调用PipedInputStream对象的receive()方法进行接收,也就是写入缓冲数组buf[]。而最终的PipedInputStream的读取就从这个buf[]缓冲数组中来。
4. SequenceInputStream
这个SequenceInputStream是InputStream的另一个实现,而且没有OutputStream与其对应(至少在java.io中没有)。这个类实际上所做的,也是一个对多个其它InputStream的“包装”,而这个所谓的“包装”的作用就是把这些依次(sequently)连接起来,当一个read()到头了(返回-1)就接着读下一个。
下面是read()方法实现:
5. StringBufferInputStream
这个类的对象是通过一个String字符串对象来构造,read()实际上就是读取其中的字节(读取到char再和0xFF与操作)。遗憾的是这个类已经被@Deprecated,即不建议使用。不多说了。
6. ObjectInputStream/ObjectOutputStream
ObjectInputStream除了extends了InputStream,还实现了ObjectOutput, ObjectStreamConstants两个接口。ObjectOutputStream也类似。
这两个类与序列化有关,后面序列化文章统一说明。
7. FilterInputStream/FilterOutputStream
我们更关心的是InputStream中的几个read()方法和OutputStream的几个write()方法。而实际上最核心的read()和write()方法,InputStream和OutputStream并未给出直接实现,这正是InputStream和OutputStream抽象的地方,我们来看下。
InputStream的read()方法:
public abstract int read() throws IOException; 核心read()方法,留给子类实现。
public int read(byte b[])
public int read(byte b[], int off, int len)
后两者是调用第一个方法读特定长度的数据放入byte数组中。
OutputStream的write()方法:
public abstract void write(int b) throws IOException; 核心write()方法,留给子类实现。
public void write(byte b[])
public void write(byte b[], int off, int len)
和read()类似,把字节数组中的特定数据挨个调用第一个write()方法写出。
再说read()和wirte()实现,那么就要看一下InputStream和OutputStream的子类。我们先来看看InputStream和OutputStream的直接子类。
在java.io中InputStream的直接子类有:
java.io.ByteArrayInputStream
java.io.FileInputStream
java.io.FilterInputStream
java.io.ObjectInputStream
java.io.PipedInputStream
java.io.SequenceInputStream
java.io.StringBufferInputStream
而java.io中OutputStream的直接子类有:
java.io.ByteArrayOutputStream
java.io.FileOutputStream
java.io.FilterOutputStream
java.io.ObjectOutputStream
java.io.PipedOutputStream
这些当中,FileInputStream和FileOutputStream是与外部IO直接有关系的,而FilterInputStream和FilterOutputStream是“装饰者”设计实现的基类,其它各类都是特定场景下InputStream和OutputStream的实现,我们来具体看看。
1. FileInputStream/FileOutputStream
顾名思义,是文件的输入流和输出流。文件存在于哪里呢?通常存在于外部设备上,这个是这些实现类中比较特殊的。我们如果做过C语言开发,知道我们通常会open操作系统中的文件,并保留其文件描述符fd。其实,在Java中我们也有类似的东西。首先,就有fd属性,它是FileDescriptor类,和C等底层语言中一样,这实际上是对底层文件的一个描述符,和底层文件进行交互的时候少不了它。实际上在FileInputStream/FileOutputStream对象构造方法中,我们初始化了FileDescriptor的fd对象,并调用了open()方法。
遗憾的是,像open()、read()、write()、skip()、available()这些FileInputStream/FileOutputStream中的具体操作方法,在(Sun)JDK中都冠以native,即本地实现,这样做的好处就是上层开发使用者不必关心,统统交由JVM等底层实现进行处理,实现了平台无关性。
在FileInputStream还有这样几个属性:
private final FileDescriptor fd;
private FileChannel channel = null; JDK1.4之后为了支持NIO的Channel操作
private final Object closeLock = new Object(); 关闭时的并发同步锁
private volatile boolean closed = false; 关闭标志
private static final ThreadLocal<Boolean> runningFinalize =
new ThreadLocal<>(); finalize是否运行的标志
此外,再简要看下FileInputStream构造方法的一个具体实现:
2. ByteArrayInputStream/ByteArrayOutputStream
名称也很直接,实际上就是字节数组,在构造类对象的时候给出一个byte数组。对于ByteArrayInputStream来说,这个byte数组就是读取的源头,而ByteArrayOutputStream则是write()的目的地。
此外,构造方法中还可以指定这个byte数组的有效起点和长度。
从名字理解也没错,就是管道输入输出(字节)流。它们的存在需要彼此,即PipedInputStream对象和PipedOutputStream对象只有互相存在才真正有意义,当然可以先构建后连接(connect)。
总体来说就是PipedInputStream维护了一个PipedOutputStream对象的属性,而PipedOutputStream也维护了一个PipedInputStream对象属性。而PipedInputStream额外维护了一个缓冲区数组。当PipedOutputStream执行write()的时候,如果PipedInputStream对象未就绪,会发生一个异常。就绪情况下会调用PipedInputStream对象的receive()方法进行接收,也就是写入缓冲数组buf[]。而最终的PipedInputStream的读取就从这个buf[]缓冲数组中来。
4. SequenceInputStream
这个SequenceInputStream是InputStream的另一个实现,而且没有OutputStream与其对应(至少在java.io中没有)。这个类实际上所做的,也是一个对多个其它InputStream的“包装”,而这个所谓的“包装”的作用就是把这些依次(sequently)连接起来,当一个read()到头了(返回-1)就接着读下一个。
下面是read()方法实现:
这个类的对象是通过一个String字符串对象来构造,read()实际上就是读取其中的字节(读取到char再和0xFF与操作)。遗憾的是这个类已经被@Deprecated,即不建议使用。不多说了。
6. ObjectInputStream/ObjectOutputStream
ObjectInputStream除了extends了InputStream,还实现了ObjectOutput, ObjectStreamConstants两个接口。ObjectOutputStream也类似。
这两个类与序列化有关,后面序列化文章统一说明。
7. FilterInputStream/FilterOutputStream
相关文章推荐
- JAVA学习笔记(二十八) - 字节流 InputStream & OutputStream
- Java学习笔记之IO(三):OutputStream输出字节流
- Java学习笔记之IO(四):BufferedInputStream缓冲输入字节流
- Java学习笔记之IO(二):InputStream输入字节流
- Java IO ---学习笔记(InputStream 和 OutputStream)
- java学习笔记(7)基本概念之IO
- 黑马程序员________Java中IO技术字节流字符流的应用及File类学习笔记
- Java IO学习【12】字节流byte Stream的基本write/read学习
- 学习笔记之java.io包中的字节流(下)—— FilterInputStream和FilterOutputStream
- Java IO操作——字节流(OutputStream、InputStream)和字符流(Writer、Reader)
- JDK 1.7 java.io 源码学习之ObjectInputStream和ObjectOutputStream
- Java IO--字节流与字符流OutputStream/InputStream/Writer/Reader
- 黑马程序员_学习笔记:13) IO流: 字节流(InputStream、OutputStream)、字符流(Reader、Writer)、File类、递归
- java IO笔记(序列化与ObjectInputStream、ObjectOutputStream)
- 我的Java开发学习之旅------>Java使用ObjectOutputStream和ObjectInputStream序列号对象报java.io.EOFException异常的解决方法
- java学习笔记IO输入与输出——IO流概述及字节流(2)
- Java IO学习笔记(三):字节流与字符流
- Java学习笔记之 IO包 字节流
- Java IO学习笔记(三):字节流与字符流
- 12. JAVA IO Party 1 (目标、File类、RandomAccessFile类、字节流和字符流、转换流) ----- 学习笔记