java IO机制
Java的IO可以说是Java语言最显著的特色。相对于C/C++,Java针对不同应用场景拥有各种各样封装好的IO对象。
了解java技术最权威和最直接的方式是查看API文档,当然需要一些英语基础。
java中的传统IO
Java的传统IO是面向流、非阻塞类型的。传统IO虽然拥有强大的灵活性,但是速度慢的缺点也很明显。
传统IO分两种:字节流和字符流。
字符流:
输入字符流(Reader):
如山发图所示Reader方法是抽象类,所以在使用输入字符流必须实现Reader类。为了提高输入字符流的的效率,可以重写Reader中的方法。
在输入字符流中含有六个输入字符流的实体类:
BufferedReader:在缓冲区读取数据,也就是说必须先把数据读入缓冲区,才能使用此方法。
CharArrayReader:读取字符数组
FilterReader:抽象类,具体实现在PushBackReader类中。
> PushBackReader:允许将字符到回推到流中
InputStreamReader:读取字符数据流到内存。输入的参数是字节流,即是重字节流中读取数据。
> FileReader:读取文件到缓冲区。
PipedReader:从管道中读取字符流。
StringReader:在字符串中读取字符流。
输出字符流(Writer):
Writer类具有和Reader类相同的性质,不同的是Writer类对应的输出字符。
在输出的字符流中含有7个输出字符流的具体类。
BufferedWriter:将数据转换成bytes。
CharArrayWriter:将数据输出为一个字符串,功能相当于toString()函数。
FilterWriter:抽象类,供自定义使用。
OutputStreamWriter:将字符流装换成byte流。
PipedWriter:输出数据到管道。
PrintWriter:将对象的格式化表示形式打印到文本输出流。
StringWriter:在字符串缓冲区中收集其输出的字符流,然后可以使用该缓冲区构造字符串。
字节流:
输入字节流(InputStream):
从上图中的API截图中可以看出InputStream是一个抽象类,其有9个具体实现类供开发者使用。
AudioInputStream:音频输入流是具有指定音频格式和长度的输入流。长度以示例帧表示,而不是以字节表示。
ByteArrayInputStream:BytearrayInputStream包含一个内部缓冲区,该缓冲区包含可以从流中读取的字节。内部计数器跟踪由read方法提供的下一个字节。
FileInputStream:
Fileinputstream从文件系统中的文件获取输入字节。哪些文件可用取决于主机环境。fileinputstream用于读取原始字节流,如图像数据。要读取字符流,请考虑使用FileReader。
FilterInputStream:filterinputstream包含一些其他的输入流,它使用这些输入流作为它的基本数据源,可能会沿途转换数据或提供其他功能。
InputStream(org.omg.CORBA.portable.InputStream):输入流是用于从CDR MARSCAL流读取IDL类型的Java API。ORB使用这些方法来解组IDL类型,并从任何类型中提取IDL类型。方法的数组版本可以直接用于读取IDL类型的序列和数组
ObjectInputStream:反序列化基元数据和以前使用ObjectOutputstream编写的对象。
PipedInputStream:管道输入流应连接到管道输出流;然后管道输入流提供写入管道输出流的任何数据字节。
SequenceInputStream:表示其他输入流的逻辑串联。它从有序的输入流集合开始,从第一个流读取,直到到达文件结尾,然后从第二个流读取,依此类推,直到在所包含的最后一个输入流上到达文件结尾。
StringBufferInputStream:此类允许应用程序创建一个输入流,其中读取的字节由字符串的内容提供。应用程序还可以使用ByteArrayInputStream从字节数组中读取字节。
输入字节流(OutputStream):
字节输出流也是一个抽象类,其提供6个具体类供开发者使用。
ByteArrayOutputStream:此类实现一个输出流,在该输出流中数据被写入字节数组。当数据写入缓冲区时,缓冲区会自动增长。可以使用tobytearray()和toString()检索数据
FileOutputStream:文件输出流是将数据写入文件或文件描述符的输出流。文件是否可用或是否可以创建取决于基础平台。
FilterOutputStream:这个类是过滤输出流的所有类的超类。这些流位于已经存在的输出流(底层输出流)的顶部,它使用这些输出流作为基本的数据接收器,但可能会沿途转换数据或提供其他功能。
> BufferedOutputStream:类实现缓冲的输出流。通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节调用底层系统。
> CheckedOutputStream:一种输出流,它还维护正在写入的数据的校验和。然后可以使用校验和验证输出数据的完整性。
> CipherOutputStream:由OutputStream和Cipher组成,因此write()方法首先处理数据,然后再将其写入底层OutputStream。
> DataOutputStream:数据输出流允许应用程序以便携的方式将原始Java数据类型写入输出流。然后,应用程序可以使用数据输入流来重新读取数据。
> DeflaterOutputStream:这个类实现了一个输出流过滤器,用于以“deflate”压缩格式压缩数据。它还用作其他类型压缩过滤器(如gzip输出流)的基础。
> DigestOutputStream:一个透明的流,它使用流经该流的位来更新关联的消息摘要。
> InflaterOutputStream:实现用于解压缩以“deflate”压缩格式存储的数据的输出流筛选器。
> PrintStream:打印流为另一个输出流添加了功能,即方便地打印各种数据值的表示形式的能力。
ObjectOutputStream:将原始数据类型和Java对象的图形写入OutputStream流。
OutputStream(org.omg.CORBA.portable.OutputStream):用于将IDL类型写入CDR队列流的Java API。ORB使用这些方法封送IDL类型,并将IDL类型插入anys。方法的数组版本可以直接用于编写IDL类型的序列和数组。
PipedOutputStream:管道输出流可以连接到管道输入流以创建通信管道。管道输出流是管道的发送端。
java中的NIO(None-block IO)
而nio是相对于传统的IO拥有快速将数据加载到本地内存的能力,所以是面向缓冲的,且是阻塞类型的。虽然速度快,但是缺乏传统IO的灵活性,在边读边处理方面性能低于传统IO性能。
nio三要素:channel, buffer,Selector
channel
一个管道就是一个程序与源数据的链接。管道一旦关闭就不能打开,如果尝试打开就会报错。其管道操作时线程安全的。
常用的Channel有:
> DatagramChannel:能通过UDP读写网络中的数据。
> FileChannel:从文件中读写数据。
> SelectableChannel:通过选择器可以实现管道的多路复用。
> SocketChannel:能通过TCP读写网络中的数据。
> ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
buffer
Buffer是一个缓冲区抽象类,其具体的实现是其实现类,针对不同的数据有7种不同类型的缓冲区,可以看出针对Java设计的集中数据类型(boolean类型除外)。
Buffer有三个重要的参数:capacity(设置缓冲区中存储数据的个数,在缓冲区的使用过程是不可变的),limit(不为负且小于capacity,第一个不能读也不能写元素的索引),position(在缓冲区中下一个可存储元素的索引,取值在limit和capacity之间)。
Selector:
Selector是SelectableChannel对象的多路复用器。
可以通过调用此类的open方法来创建选择器,该方法将使用系统的默认选择器提供程序来创建新的选择器。也可以通过调用自定义选择器提供程序的openselector方法来创建选择器。选择器保持打开状态,直到通过其关闭方法关闭。
可选择通道的选择器注册由SelectionKey对象表示。选择器维护三组选择键:
> key set包含表示此选择器当前频道注册的键。这个集合由keys方法返回。
> selected-key set是一组密钥,以便在之前的选择操作期间检测到每个密钥的通道已准备就绪,可以进行密钥的兴趣集中标识的至少一个操作。此集合由SelectedKeys方法返回。选定的键集始终是键集的子集
> cancelled-key是已取消但其通道尚未取消注册的密钥集。此集合不能直接访问。cancelled-key set始终是密钥集的子集。
注意 selector时线程安全的,但是key set不是线程安全的。
BIO 同步阻塞IO(Block IO)
应用在数据传输对象是一对一的场景下
AIO 异步IO(Asyncronous IO)
应用在一个有效请求一个线程,发起和处理IO请求都是异步的