Java IO和Java NIO

1. Java IO

简介
为了实现“文件、控制台、网络设备”这些IO设置的通信,我们设计了Java IO。Java IO对应文件组成单位分成以字节为单位和以字符为单位。
Java提供的类都是以字节(byte)为单位,例如,FileInputStream和FileOutputStream。而到了java 1.1,为了与国际化进行接轨,在Java io中添加了许多以字符(Unicode)为单位进行操作的类。

Java IO流的概念

在Java IO的称呼中,我们经常会提到“输入流”、“输出流”等等概念。首先,什么是流呢?
所谓“流”,就是一种抽象的数据的总称,它的本质是能够进行传输。
      a) 按照“流”的数据流向,可以将其化分为:输入流和输出流。
      b) 按照“流”中处理数据的单位,可以将其区分为:字节流和字符流。在Java中,字节是占1个Byte,即8位;而字符是占2个Byte,即16位。而且,需要注意的是,Java的字节是有符号类型,而字符是无符号类型。

以字节为单位的输入输出流

该图中左面是以字节为单位的输出流框架,右边是以字节为单位的输入流框架。
在以字节为单位的输入流中:
01) InputStream 是以字节为单位的输入流的超类。InputStream提供了read()接口从输入流中读取字节数据。
(02) ByteArrayInputStream 是字节数组输入流。它包含一个内部缓冲区,该缓冲区包含从流中读取的字节;通俗点说,它的内部缓冲区就是一个字节数组,而ByteArrayInputStream本质就是通过字节数组来实现的。
(03) PipedInputStream 是管道输入流,它和PipedOutputStream一起使用,能实现多线程间的管道通信。
(04) FilterInputStream 是过滤输入流。它是DataInputStream和BufferedInputStream的超类。
(05) DataInputStream 是数据输入流。它是用来装饰其它输入流,它“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”。
(06) BufferedInputStream 是缓冲输入流。它的作用是为另一个输入流添加缓冲功能。
(07) File 是“文件”和“目录路径名”的抽象表示形式。关于File,注意两点:
a), File不仅仅只是表示文件,它也可以表示目录!
b), File虽然在io保重定义,但是它的超类是Object,而不是InputStream。
(08) FileDescriptor 是“文件描述符”。它可以被用来表示开放文件、开放套接字等。
(09) FileInputStream 是文件输入流。它通常用于对文件进行读取操作。
(10) ObjectInputStream 是对象输入流。它和ObjectOutputStream一起,用来提供对“基本数据或对象”的持久存储。

 

以字节为单位的输出流中:
(01) OutputStream 是以字节为单位的输出流的超类。OutputStream提供了write()接口从输出流中读取字节数据。
(02) ByteArrayOutputStream 是字节数组输出流。写入ByteArrayOutputStream的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。
(03) PipedOutputStream 是管道输出流,它和PipedInputStream一起使用,能实现多线程间的管道通信。
(04) FilterOutputStream 是过滤输出流。它是DataOutputStream,BufferedOutputStream和PrintStream的超类。
(05) DataOutputStream 是数据输出流。它是用来装饰其它输出流,它“允许应用程序以与机器无关方式向底层写入基本 Java 数据类型”。
(06) BufferedOutputStream 是缓冲输出流。它的作用是为另一个输出流添加缓冲功能。
(07) PrintStream 是打印输出流。它是用来装饰其它输出流,能为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
(08) FileOutputStream 是文件输出流。它通常用于向文件进行写入操作。
(09) ObjectOutputStream 是对象输出流。它和ObjectInputStream一起,用来提供对“基本数据或对象”的持久存储。

以字节为单位的输入输出流

以字符为单位的输入流中:
(01) Reader 是以字符为单位的输入流的超类。它提供了read()接口来取字符数据。
(02) CharArrayReader 是字符数组输入流。它用于读取字符数组,它继承于Reader。操作的数据是以字符为单位!
(03) PipedReader 是字符类型的管道输入流。它和PipedWriter一起是可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedWriter和PipedReader配套使用。
(04) FilterReader 是字符类型的过滤输入流。
(05) BufferedReader 是字符缓冲输入流。它的作用是为另一个输入流添加缓冲功能。
(06) InputStreamReader 是字节转字符的输入流。它是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
(07) FileReader 是字符类型的文件输入流。它通常用于对文件进行读取操作。

 


以字符为单位的输出流中:
(01) Writer 是以字符为单位的输出流的超类。它提供了write()接口往其中写入数据。
(02) CharArrayWriter 是字符数组输出流。它用于读取字符数组,它继承于Writer。操作的数据是以字符为单位!
(03) PipedWriter 是字符类型的管道输出流。它和PipedReader一起是可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedWriter和PipedWriter配套使用。
(04) FilterWriter 是字符类型的过滤输出流。
(05) BufferedWriter 是字符缓冲输出流。它的作用是为另一个输出流添加缓冲功能。
(06) OutputStreamWriter 是字节转字符的输出流。它是字节流通向字符流的桥梁:它使用指定的 charset 将字节转换为字符并写入。
(07) FileWriter 是字符类型的文件输出流。它通常用于对文件进行读取操作。
(08) PrintWriter 是字符类型的打印输出流。它是用来装饰其它输出流,能为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。

字节转换为字符流

2. Java NIO

NIO主要有三大核心部分组成:Channel(通道) + Buffer(缓冲区) + Selector(选择器)

传统IO基于字节流和字符流进行操作,而NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。

NIO的三大特点:面向缓冲 + 非阻塞 + 异步

阻塞与非阻塞

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.

Java IO流都是阻塞的,这意味着,当一条线程执行read()或者write()方法时,这条线程会一直阻塞直到读取到了一些数据或者要写出去的数据已经全部写出,在这期间这条线程不能做任何其他的事情。java NIO的非阻塞模式(Java NIO有阻塞模式和非阻塞模式,阻塞模式的NIO除了使用Buffer存储数据外和IO基本没有区别)允许一条线程从channel中读取数据,通过返回值来判断buffer中是否有数据,如果没有数据,NIO不会阻塞,因为不阻塞这条线程就可以去做其他的事情,过一段时间再回来判断一下有没有数据。NIO的写也是一样的,一条线程将buffer中的数据写入channel,它不会等待数据全部写完才会返回,而是调用完write()方法就会继续向下执行。

举个例子,你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。在这里阻塞与非阻塞与是否同步异步无关。

同步与异步

同步和异步关注的是消息通信机制

所谓同步,就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由*调用者*主动等待这个*调用*的结果。而异步则是相反,*调用*在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。

例子:你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。

参考文献: 1. https://www.jianshu.com/p/88ec3430ae8b

2. https://www.jianshu.com/p/a6b7410a6fbe

3. http://www.cnblogs.com/skywang12345/p/io_01.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值