在计算机术语中,I/O(input/output)是系统和外部进行交流通讯的方式。输入(input)是系统收到的信号或者数据,输出是系统对外发出的信号或者数据。咱们一般所说的执行I/O操做就是对于输入或者输出数据的处理。java
Java IO是Java提供的一系列用于处理输入和输出数据的API。Java对于输入和输出进行了抽象,用流(Stream)来表示输入输出。流能够表明任何类型的输入源或者输出目标。好比硬盘上的文件,内存,其余设备等。 流由一系列的数据组成,你能够把流想象成水流,程序可使用输入流来读取数据,使用输出流来写出数据。流支持不一样类型的数据,如字节数据,基本类型数据,对象等数组
从流中读取数据 缓存
向流中写入数据 性能
Java Stream中根据处理数据的最小单位不一样,能够分为字节流和字符流两种。编码
字节流操作系统
数据流中最小的数据单元是字节线程
字符流 数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。3d
根据这两种不一样的类型,Java提供了一些列的Java类code
InputStream是全部字节输入流的基类,提供了读取字节流的基本方法,其子类经过继承InputStream实现不一样形式的字节流。咱们先看下InputStream中的关键方法cdn
方法 | 方法介绍 |
---|---|
public abstract int read() | 从流中读取一个字节数据,抽象方法由子类负责实现真正的读取 |
public int read(byte b[]) | 从流中读取数组长度的字节数据,内部调用下面的方法实现 |
public int read(byte b[], int off, int len) | 从流中读取len个字节,写入到从off位置开始的数组中 |
public long skip(long n) | 跳过流中的几个字节 |
public int available() | 流中可读字节的数量 |
public void close() | 关闭字节流,释放系统资源 |
public synchronized void mark(int readlimit) | 标记当前位置,调用reset方法以后还能够从当前位置开始读取,调用前须要经过markSupported检查实现类四是否支持mark |
public synchronized void reset() | 重置读取位置为上次 mark 标记的位置 |
public boolean markSupported() | 判断当前流是否支持标记流 |
ByteArrayInputStream把一个数组包装成输入流,从字节数组读取数据。相比于直接使用原始数组,ByteArrayInputStream提供了read-only功能。由于流没有提供更改数组内容的方法。
FileInputStream从文件系统中读取字节数据,是咱们使用比较多的一个类,内部实际读取文件内容的方法为native方法实现,通常读取配置包装类BufferedInputStream使用,减小I/O消耗。
PipedInputStream主要用户线程间通讯,PipedInputStream链接到PipedOutputStream,一个线程经过PipedOutputStream写数据,另一个经过PipedInputStream读取数据。可是线程间通讯也能够采起共享内存到方式。因此使用过程当中应用场景很少。
咱们都知道Java IO包使用了经典的装饰模式,经过装饰器增长原始输入输出流的功能。FilterInputStream是输入装饰器的基类,自己没有提供特殊的功能,只是简单的把调用转发到原始输入流中。具体装饰器经过实现类来扩展。
BufferedInputStream
BufferedInputStream是咱们使用比较多的类,提供了读取输入的缓存功能,经过一次读取和缓存多个字节的数据到内存中,减小系统调用带来的开销。可是要注意的是并非任何状况下经过BufferedInputStream都能提升读取的性能,经过阅读源码能够发现,BufferedInputStream默认读取8K(8192)的缓存数据,若是你一次读取的字节超过了缓存大小的数据,反而增长了一次数据的内存拷贝,下降了程序的性能。因此须要根据自身程序特色决定是否使用。
PushbackInputStream
回退流,咱们的输入流在只能顺序的从前日后读取字节,PushbackInputStream提供了回退功能,把读取进来不须要的字节回退到输入流的缓存中。
DataInputStream
DataInputStream提供了咱们从输入流中读取Java基本数据类型数据的功能。根据数据类型字节长度不一样,读取相应的字节,转换为咱们须要的基本数据类型。好比int类型,读取流中的四个字节,经过移位的方式组合成咱们须要的int类型数据。
ObjectInputStream用于对象的反序列化,从流中读取数据,转换为咱们须要的Java对象。对象反序列化的过程不包括transient和静态字段。可反序列化的对象必须实现Serializable接口。
OutputStream是全部字节输出流的基类,提供了写出数据的基本方法,其子类经过继承OutputStream实现不一样形式的字节输出流。咱们先看下OutputStream中的关键方法
方法 | 方法介绍 |
---|---|
public abstract void write(int b) | 向输出流中写入一个字节,取的是int的低八位字节 |
public void write(byte b[]) | 向输出流中写入字节数组 |
public void write(byte b[], int off, int len | 向输出流中写入len长度的字节数据,从b[]的off位置开始 |
public void flush() | 强制刷新,将缓冲中的数据写入的输出流。这里只是保证写入到输出流,,好比文件,只是保证写入到操做系统缓存。 |
public void close() | 关闭字节流,释放系统资源 |
ByteArrayOutputStream写入到内存中的字节数组缓存中,数组大小会随着写入数量的增长而自动增加。能够经过toByteArray或者toString获取写入的数据
FileOutputStream写入字节到文件中
PipedOutputStream管道输出流须要和PipedOutputStream配合使用,用于线程间通讯。
FilterOutputStream和FilterInputStream相似,是输出字节流的装饰类的基类,自己没有提供特殊的功能,只是简单的把调用转发到原始输入流中。具体装饰器经过实现类来扩展。
ObjectOutputStream用于对象的序列化,把Java对象对象写入到输出流中。对象序列化的过程不包括transient和静态字段。可序列化的对象必须实现Serializable接口。
字符流和字节流相似,基本的类结构和方法和字节流也基本相同。不一样过的是字符流读取的单位是字符,而字节流是单个字节。须要注意的是FileReader和FileWriter,不是直接继承的Reader和Writer抽象类,而是经过OutputStreamReader和OutputStreamWriter进行桥接,底层依然使用的FileInputStream和FileOutputStream。
原文地址: blog.devlab.cn/java-io/#mo…