用户进程发起请求,内核接收到请求后,从I/O设备中获取数据到buffer中,再将buffer中的数据copy到用户进程的地址空间,该用户进程获取到数据后再响应客户端。
数据输入到buffer需要时间,从buffer复制数据至进程也需要时间,根据在这两段时间内等待方式不同,I/O动作可分为五种模式
- 阻塞I/O(Blocking I/O)
- 非阻塞I/O(Non-Blocking I/O)
- I/O复用(I/O Multiplexing)
- 信号驱动I/O
- 异步I/O
java的I/O操作在类的java.io包中
-
基于字节操作的I/O接口: InputStream和OutputStream
-
基于字符操作的I/O接口: Writer和Reader
-
基于磁盘操作的I/O接口: File
-
基于网络操作的I/O接口: Socket(网络编程,不在io包中)
普通IO
-
字节流对应原生的二进制数据
-
字符流对应字符数据,会自动处理与本地字符集之间的转换
-
缓冲流可以提高性能,通过减少底层API的调用次数来优化IO
字节流
输入流
字节输入流都继承自InputStream,InputStream表示从不同数据源产生输入的类,这些数据员包括
- 字节数组
- String对象
- 文件
- 管道,从一端输入,从另一端输出
- 一个由其他种类的流组成的序列,然后把它们汇聚为一个流
- 其他数据源,如Internet连接
类 | 功能 | 构造器 | 如何使用 |
---|---|---|---|
ByteArrayInputStream | 允许将内存的缓冲区当做InputStream使用 | 缓冲区,字节将从中取出 | 将其与FilterInputStream对象相连以提供有用接口 |
StringBufferInputStream | 将String转换为InputStream | 字符串。底层实现实际使用StringBuffer | 将其与FilterInputStream对象相连以提供有用接口 |
FileInputStream | 用于从文件中读取信息 | 字符串,表示文件名、文件或FileDescriptor对象 | |
PipedInputStream | 产生用于写入相关PipedOutputStream的数据。实现管道化概念 | PipedOutputStream | 作为多线程中的数据源 |
SequenceInputStream | 将两个或多个InputStream对象转换成一个InputStream | 两个InputStream对象或一个容纳InputStream对象的容器Enumeration | |
FilterInputStream | 抽象类,作为装饰器的接口,为其他的InputStream类提供有用的功能 |
FilterInputStream类型子类包括以下几种
类 | 功能 | 构造器 | 如何使用 |
---|---|---|---|
DataInputStream | 与DataOutputStream搭配使用,按照移植方式从流读取基本数据类型 | InputStream | 包含用于读取基本数据类型的全部接口 |
BufferedInputStream | 使用它可以防止每次读取时都得进行实际写操作 | InputStream | 本质上不提供接口,只是向进程添加缓冲功能 |
LineNumberInputStream | 跟踪输入流的行号,可调用getLineNumber()和setLineNumber(int) | InputStream,可以指定缓冲区大小 | 仅增加了行号 |
PushbackInputStream | 具有能弹出一个字节的缓冲区,因此可以将读到的最后一个字符回退 | InputStream | 通常作为编译器的扫描器 |
输出流
字节输入流都继承自OuputStream,该类决定了输出所要去的目标,字节数组、文件或管道
类 | 功能 | 构造器 | 如何使用 |
---|---|---|---|
ByteArrayOutputStream | 在内存中创建缓冲区。所有送往流的数据都要放置在此缓冲区 | 缓冲区初始大小 | 用于指定数据的目的地 |
FileOutputStream | 用于将信息写入文件 | 字符串,表示文件名、文件或FileDescriptor对象 | |
PipedOutputStream | 任何写入其中的信息都会自动作为相关PipedInputStream的输出,实现管道化概念 | PipedInputStream | 指定用于多线程的数据的目的地 |
FilterOutputStream | 抽象类,作为装饰器的接口,为其他OutputStream提供有用的功能 |
FilterOutputStream类型子类包括
类 | 功能 | 构造器 | 如何使用 |
---|---|---|---|
DataOutputStream | 与DataInputStream搭配使用,可以按照移植方式向流中写入基本数据类型 | OutputStream | 包含用于写入基本数据类型的全部接口 |
PrintStream | 用于产生改格式化输出。其中DataOutputStream处理数据的存储,PrintStream处理显示 | OutputStream,可以用boolean值指示是否每次换行时清空缓冲区 | 应该是对OutputStream对象的final封装 |
BufferedOutputStream | 使用它以避免每次发送数据时都进行实际的写操作,可以调用flush()清空缓冲区 | OutputStream,可以指定缓冲区大小 | 只是向进程添加缓冲功能 |
字符流
InputStream和OutputStream是面向字节I/O的,而Reader和Writer则提供兼容Unicode和面向字符I/O的功能,InputStreamReader可以把InputStream转换为Reader,而OutputStreamWriter可以把OutputStream转换为Writer
RandomAccessFile类
适用于由大小已知的记录组成的文件,可以使用seek()将文件指针从一条记录移动到另一条记录,然后对记录进行读取和修改。文件中记录的大小不一定相同,只要我们能确定那些记录有多大以及它们在文件中的位置即可。
RandomAccessFile类不是InputStream或者OutputStream的子类,只是实现了DataInput和DataOutput接口,没有使用InputStream和OutputStream的任何功能,所有方法都是独立的,大部分为native方法
常用的IO操作
缓冲输入文件
想要打开一个文件进行字符输入,可以使用FileReader对象,然后传入一个String或者File对象作为文件名。为了提高速度,对文件进行缓冲,可以将所产生的引用传递给一个BufferedReader构造器。BufferedReader提供了lines()方法,会产生一个Stream
public static void read(String file) {
try(BufferedReader bufferedReader = new BufferedReader(new FileReader(file))){
String line = null;
while((line = bufferedReader.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
throw new RuntimeException("读取失败",e);
}
}
读取字符
public static void read() throws IOException {
StringReader stringReader = new StringReader("qaw试试");
int c;
while ((c = stringReader.read()) != -1) {
System.out.println((char)c);
}
}
StringReader的read方法是以int形式返回的下一个字节,所以打印的时候类型必须转为char
格式化数据
要读取格式化数据,可以使用DataInputStream,是面向字节的,所以要使用InputStream类
文件输出
FileWrite对象用于向文件写入数据,通常使用BufferedWriter将其包装起来增加缓冲的功能,
try(BufferedReader in = new BufferedReader(new StringReader("1111111111111111\n2222222222222\n3333333333"));
PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter("test.txt")))
){
in.lines().forEach(printWriter :: println);
} catch (IOException e) {
e.printStackTrace();
}
标准IO
标准输入流Systom.in、标准输出流System.out、标准错误流Sytem.err。
System.out和System.err是预先包装成了PrintStream对象,但是System.in没有进行包装,属于原生的InputStream,所以在读取时需要对其进行包装
标准输入
通常一行一行地读取输入,将System.in包装成BufferedReader
public static void main(String[] args) {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
if (line.equals("end")) {
break;
}
System.out.println(line);
}
} catch (IOException e) {
}
}
重定向标准I/O
System类提供了简单的静态方法调用,重定向标准输入流、标准输出流和标准错误流
-
setIn(InputStream)
-
setOut(PrintStream)
-
setErr(PrintStream)
public static void main(String[] args) {
try(BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\sinosoft\\Desktop\\剩余工作.txt"));
PrintStream printStream = new PrintStream(new BufferedOutputStream(new FileOutputStream("C:\\Users\\sinosoft\\Desktop\\剩余工作副本.txt")))
){
System.setIn(bufferedInputStream);
System.setOut(printStream);
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
if (line.equals("end")) {
break;
}
System.out.println(line);
}
} catch (IOException e1) {
}
}catch (IOException e){
}
}
由于本身的博客百度没有收录,博客地址http://zhhll.icu