1、Java 中有几种类型的流?
按数据流向:
输入流(inputStream)和输出流(outputStream)。
按照实现功能分:
节点流(可以从或向一个特定的地方(节点)读写数据。如 FileReader)和处理流(是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如 BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。)
按照处理数据的单位:
字节流和字符流。字节流继承于 InputStream 和 OutputStream,字符流继承于
InputStreamReader 和 OutputStreamWriter。
2、常用的流有哪些?
1)对文件进行操作:FileInputStream(字节输入流)、
FileOutputStream(字节输出流)、FileReader(字符输入流)、FileWriter(字符输出流)
2)对管道进行操作:PipedInputStream(字节输入流)、PipedOutStream(字节输出流)、PipedReader(字符输入流)、PipedWriter(字符输出流)
3)字节/字符数组:ByteArrayInputStream、ByteArrayOutputStream、CharArrayReader、CharArrayWriter
4)Buffered 缓冲流:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
5)字节转化成字符流:InputStreamReader、OutputStreamWriter
6)数据流:DataInputStream、DataOutputStream
7)打印流:PrintStream、PrintWriter
8)对象流:ObjectInputStream、ObjectOutputStream
9)序列化流:SequenceInputStream
3、BIO、NIO、AIO 有什么区别?
BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。
NIO (New I/O): NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。NIO提供了与传统BIO模型中的Socket和ServerSocket相对应de的SocketChannel和ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。
AIO (Asynchronous I/O): AIO也就是 NIO 2。在 Java 7 中引入了NIO的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步IO的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。
总结来说的话:
BIO:线程发起 IO 请求,不管内核是否准备好 IO 操作,从发起请求起,线程一直阻塞,直到操作完成。
NIO:线程发起 IO 请求,立即返回;内核在做好 IO 操作的准备之后,通过调用注册的回调函数通知线程做 IO 操作,线程开始阻塞,直到操作完成。
AIO:线程发起 IO 请求,立即返回;内存做好 IO 操作的准备之后,做 IO 操作,直到操作完成或者失败,通过调用注册的回调函数通知线程做 IO 操作完成或者失败。
4、字节流和字符流的区别?
Java 中的字节流处理的最基本单位为 1 个字节,通常用来处理二进制数据(比如图片,视频)。字节流类 InputStream 和 OutputStream 类均为抽象类,代表了基本的输入字节流和输出字节流。
Java 中的字符流处理的最基本的单元是 Unicode 代码单元(大小2字节),通常用来处理文本数据。
字节流操作的基本单元是字节;字符流操作的基本单元是字符;
字节流默认不使用缓冲区;字符流使用缓冲区;
字节流通常用于处理二进制数据,不支持直接读写字符;字符流通常用于处理文本数据;
在读写文件需要对文本内容进行处理:按行处理、比较特定字符的时候一般会选择字符流;仅仅读写文件,不处理内容,一般选择字节流;
5、 字节流如何转为字符流?
字节输入流转字符输入流通过 InputStreamReader 实现,该类的构造函数可以传入 InputStream 对象。
字节输出流转字符输出流通过 OutputStreamWriter 实现,该类的构造函数可以传入 OutputStream 对象。
6、节点流和处理流的区别?
节点流:可以从某节点读数据或向某节点写数据的流。如 FileInputStream;
处理流:对已存在的流的连接和封装,实现更为丰富的流数据处理,处理流的构造方法必需其他的流对象参数。如 BufferedReader。
7、输入流和输出流的区别?
输入输出的方向是针对程序而言,向程序中读入数据,就是输入流;从程序中向外写出数据,就是输出流;
从磁盘、网络、键盘读到内存,就是输入流,用 InputStream 或 Reader;
写到磁盘、网络、屏幕,都是输出流,用 OuputStream 或 Writer。
8、什么是 java 序列化,如何实现 java 序列化?
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。
序 列 化 的 实 现 : 将 需 要 被 序 列 化 的 类 实 现 Serializable 接 口 , 该 接 口 没 有 需 要 实 现 的 方 法 ,implements Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个 ObjectOutputStream(对象流)对象,接着,使用 ObjectOutputStream 对象的 writeObject(Object obj)方法就可以将参数为 obj 的对象写出(即保存其状态),要恢复的话则用输入流。
9、为什么要使用缓冲流?
缓冲流作用是把数据先写入缓冲区,等缓冲区满了,再把数据写到文件里。这样就大大提高了效率;如果不用缓冲流的话,程序是读一个数据,写一个数据。这样在数据量大的程序中非常影响效率。
未完待续