面试直击之javaSE复习——IO

1.什么是IO流?

IO流是一种从源头到目的地的数据流,即以流的方式进行输入和输出。比如文件拷贝,输入流从文件中读取数据存储到进程中,输出流从进程中读取然后写入到目标文件。

2.Java中有几种类型的流?

按照流的方向:输入流(inputStream)和输出流(outputStream)。

按照实现功能分:节点流(可以从或向一个特定的地方(节点)读写数据,如FileReader)和处理流(是对一个已存在的流的连接和封装),通过所封装的流的功能调用实现数据读写,如Bufferedreader。处理流的构造方法总是要带一个其他的流对象做参数,一个流对象经过其他流的多次包装,成为流的连接)。

按照处理数据的单位:字节流和字符流。字节流继承于inputStream和OutputStream,字符流继承于InputStreamReader和OutputStreamWriter。

面试直击之javaSE复习——IO

 

3.字节流如何转为字符流

字节输入流转字符输入流通过InputStreamReader实现,该类的构造器可以传入InputStream对象;

字节输出流转字符输出流通过OutputStream实现,该类构造器可以传入OutputStream对象。

4.字节流和字符流的区别

1)字节流可以处理所有类型数据,如图片,MP3,AVI视频文件,而字符流只能处理字符数据,只要是处理纯文本数据,就要考虑使用字符流,除此之外都用字节流。

字节流主要处理二进制数据,它是按照字节来处理的,但实际中很多的数据是文本,因此又提出了字符流的概念,它是按照虚拟机的encode来处理的,也就是要进行字符集的转化。这两个之间通过InputStreamReader,OutputStreamWriter来关联,实际上是通过byte[]和String来关联的。

在实际开发中出现的乱码问题实际上就是字符流和字节流之间的转化不统一造成的。在从字节流转化为字符流时,实际上就是byte[]转化为String时,public String(byte byte[],String  charsetName),其中有一个关键的参数字符集编码,通常我们都省了,那系统就用操作系统的lang。而在字符流转化为字节流时,实际上就是String转化为byte[]时,byte[] String.getBytes(String charsetName)也是一样的道理。

2)字符流使用了缓冲区,而字节流没有使用缓冲区。

字符流操作时使用了缓冲区,在关闭字符流时,会强制的将缓冲区的内容进行输出,但是如果程序没有关闭,则缓冲区的内容是无法输出的。

那么什么是缓冲区呢?缓冲区可以简单理解为一段特殊的内存区域。某些情况下,如果一个程序频繁的操作一个资源(如文件或数据库),则性能会很低,此时为了提升性能,就可以将一部分数据暂时读入到内存的一块区域中,以后直接从此区域中读取数据即可,因为读取内存的速度会比较快,因此这样可以提升程序的性能。在字符流的操作中,所有的字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存之中,所以使用了缓冲区暂存数据。如果想在不关闭时也可以将字符流的内容全部输出,则可以使用Writer类中的flush()方法强制性清空缓冲区。

5.什么是.Java序列化?如何实现Java序列化?序列化的用途?

序列化:把Java对象转换为字节序列的过程。

反序列化:把字节序列恢复为Java对象的过程。

简要解释:序列化就是一种用来处理对象流的机制,所谓的对象流就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可以将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。

详细解释:当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。

序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,只是为了标注该对象是可被序列化的,然后使用一个输入流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则使用输入流。

序列化的用途:①把对象的字节序列永久的保存到硬盘上,通常存放在一个文件中;②在网络上传送对象的字节序列。

6.如何实现对象克隆

1)实现Cloneable接口并重写Object类中的clone()方法;

2)实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以真正的实现深度克隆。基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定可以检查出克隆的对象是否支持序列化,这项检查是通过编译器完成的,不是在运行时抛出异常,这种方案是明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是好过把问题留到运行时。

7.明确操作的数据设备。
数据source对应的设备:硬盘(File),内存(数组),键盘(System.in)
数据destination对应的设备:硬盘(File),内存(数组),控制台(System.out)。

只要一读取键盘录入,就用下面这段代码:
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

8.在文件拷贝时,哪一种流可用于提升更多的性能。

1)在字节流的时候,使用BufferedInputStream和BufferedOutputStream;

2)在字符流的时候,使用BufferedReader和BufferedWriter。