IO核心知识(内核、IO模型、字节流、装饰、字符流、Closable)

来源:互联网 发布:js判断时间间隔 编辑:程序博客网 时间:2024/06/06 03:40
IO核心知识

预备知识
1、内核空间与用户空间
操作系统采用虚拟存储器,虚拟存储空间(提示:x位系统的存储空间大小为2^x byte,)可分为内核空间和用户空间。内核空间管理硬件设备,并提供系统调用。
于是有如下步骤:
用户空间通过系统调用访问内核空间,内核空间通过驱动访问硬件。

2、系统调用需要等待哪些操作?
①等待内核空间通过驱动发送指令,将读的数据传输到文件描述符(File Descriptor)指向的结构体指针的缓冲区中,并将文件描述符返回给用户区。
②等待用户区通过文件描述符将内核空间的缓冲区数据传输到用户区。



5种IO模型
1、阻塞式IO
系统调用后,便进入阻塞状态,等待上面的①、②操作完成。

2、非阻塞式IO
系统调用后,立即返回文件描述符,此时需要状态码来判断操作发生错误、操作未完成还是操作已完成。由于可能操作未完成,则需要不断的轮询。

3、复用式IO
由于非阻塞式IO需要不断进行用户空间的轮询,而复用式IO使用内核空间的轮询,提升效率。

4、信号驱动式IO
系统调用后,将不用等待上面的①操作完成,内核空间数据准备好后,将会通知用户空间。

5、异步IO
系统调用后,将不用等待上面的①、②操作完成。用户数据准备好后,将会通知应用程序。



常用IO流
IO流的数据源是字节或字节数组,当然基本数据类型、对象、文件都能转换为字节数组。

1、InputStream
InputStream是一个抽象类,即表示所有字节输入流实现类的基类。
InputStream定义了一套IO规范,并没有具体的实现。
核心方法
//读取一个字节
public abstract int read() throws IOException;

2、OutputStream
OutputStream也是一个抽象类,即表示所有字节输入流实现类的基类。
核心方法
//写入一个字节
public abstract void write(int b) throws IOException;

3、FilterInputStream和FilterOutputStream
FilterInputStream是为各种InputStream实现类提供的“装饰器模式”的基类。因此,可以分为原始的字节流和“装饰”过的功能封装字节流。

FilterInputStream核心方法
//构造器
public FileInputStream(File file) throws FileNotFoundException {
//略...
this.fd = new FileDescriptor();
this.fd.incrementAndGetUseCount();
this.path = name;
open(name);
}
//打开文件
private native void open(String name) throws FileNotFoundException;
//读取一个字节
private native int read0() throws IOException;

FilterOutputStream核心方法
//构造器
public FileOutputStream(File file, boolean append) throws FileNotFoundException { //略...
this.fd = new FileDescriptor(); this.append = append; this.path = name; fd.incrementAndGetUseCount(); open(name, append);}
//打开文件
private native void open(String name) throws FileNotFoundException;
//写入一个字节
private native void write(int b, boolean append) throws IOException;

Buffered和Data
1、Buffered
BufferedInputStream能为输入流提供缓冲区,能提高很多IO的速度。你可以一次读取一大块的数据,而不需要每次从网络或者磁盘中一次读取一个字节。特别是在访问大量磁盘数据时,缓冲通常会让IO快上许多。
与BufferedInputStream类似,BufferedOutputStream可以为输出流提供缓冲区。
唯一不同的是,需要手动flush()方法确保写入到此输出流的数据真正写入到磁盘或者网络中。

2、Data
DataInputStream可以使你从输入流中读取Java基本类型数据。
DataOutputStream可以往输出流中写入Java基本类型数据。



Reader和Writer
1、Reader
Reader是一个抽象类,即表示所有字符输入流实现类的基类。
Reader定义了字符流操作的规范,并没有具体的实现。
核心方法
//读取字符数组,由子类实现
abstract public int read(char cbuf[], int off, int len) throws IOException;
实现类有InputStreamReader、BufferedReader(推荐)。

2、Writer
Writer也是一个抽象类,即表示所有字符输入流实现类的基类。
核心方法
//写入一个字节
public abstract void write(int b) throws IOException;
public void write(int c) throws IOException {
se.write(c);
}
实现类有OutputStreamWriter、BufferedWriter、PrintWriter(推荐)。
为什么推荐PrintWriter呢?
1、PrintWriter的构造方法更多,可传入字符串(文件路径)、File、OutputStream、Writer,并可以设置编码类型和自动Flush。
2、PrintWriter的print、println方法可以接受任意类型的参数,而BufferedWriter的write方法只能接受字符、字符数组和字符串。PrintWriter的println方法自动添加换行,BufferedWriter需要显示调用newLine方法。
3、PrintWriter的方法不会抛异常,若关心异常,需要调用checkError方法看是否有异常发生



try-with-resource
我们可以看到InputStream、OutputStream实现了Closable接口。

然后发现Closable继承AutoClosable接口。

AutoClosable是JDK1.7引入的,它会自动帮我们执行关闭操作。

编译器将Java代码编译成字节码的时候,会在try-with-resource的代码片段后添加执行close方法的字节码指令。
原创粉丝点击