Java IO
InputStream
实现了Closeable接口 Closeable接口又继承了AutoCloseable接口.所以InputStream的所有实现类都可以使用try(resource)语句.
available
用来查看流的大小
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("/Users/Desktop/json/sql_idx.json");
System.out.println(fileInputStream.available());
}
int read()
读取输入流的下一个字节(8个二进制位)。这是一个抽象方法,不提供实现,子类必须实现这个方法。该方法读取下一个字节,返回一个0-255之间的int类型整数。如果到达流的末端,返回-1. 调用该方法的时候,方法阻塞直到出现下列其中一种情况:1)遇到流的尾部(end of the stream)。2)有数据可以读入。3)抛出异常。
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("/Users/wangleshan/Desktop/json/sql_idx.json");
while (fileInputStream.available() > 0) {
int result = fileInputStream.read();
System.out.println(result);
}
}
int read(byte b[])
读取流内的数据到一个byte[]缓冲区
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("/Users/wangleshan/Desktop/json/sql_idx.json");
byte[] arr = new byte[fileInputStream.available()];
fileInputStream.read(arr);
String result = new String(arr);
System.out.println(result);
}
long skip(long n)
跳过前n个字节
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("/Users/wangleshan/Desktop/json/sql_idx.json");
byte[] arr = new byte[fileInputStream.available()];
fileInputStream.skip(600L);
fileInputStream.read(arr);
String result = new String(arr);
System.out.println(result);
}
void close()
关闭当前流,释放资源
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("/Users/wangleshan/Desktop/json/sql_idx.json");
byte[] arr = new byte[fileInputStream.available()];
fileInputStream.skip(600L);
fileInputStream.read(arr);
String result = new String(arr);
System.out.println(result);
fileInputStream.close();
}
InputStream
void write(int b)
将1个字节写入文件流
public static void main(String[] args) throws Exception {
FileOutputStream fileOutputStream = new FileOutputStream("/Users/wangleshan/Desktop/json/test.json");
fileOutputStream.write(72);
fileOutputStream.close();
}
void write(byte b[])
把一个byte数组写入文件流
public static void main(String[] args) throws Exception {
FileOutputStream fileOutputStream = new FileOutputStream("/Users/wangleshan/Desktop/json/test.json");
byte[] bytes = "Hello".getBytes(StandardCharsets.UTF_8);
fileOutputStream.write(bytes);
fileOutputStream.close();
}
void flush()
刷新此输出流并强制写出所有缓冲的输出字节。
阻塞/非阻塞、同步/异步
背景:Linux环境下的network IO
IO操作的两个阶段
-
等待数据准备(Waitingfor the data to be ready)
-
将数据从内核拷贝到进程中(Copyingthe data from the kernel to the process)
这两点很重要,因为这些IO Model的区别就是在两个阶段上各有不同的情况。是否阻塞说的是第一个阶段,即等待数据准备阶段是否会阻塞,而是否同步说的是第二阶段,即将数据从内核拷贝到进程这个真实的IO Operation操作阶段是否阻塞。
阻塞式
两个阶段都阻塞
非阻塞
用户进程在第一阶段发起read操作,如果内核没有准备好,则直接返回一个error,所以在内核准备数据阶段不会阻塞.在第二阶段 从内核拷贝到进程是真实的IO,会阻塞
第一阶段不阻塞,第二阶段阻塞
多路复用IO
用户调用select,整个进程阻塞,同时内核会监视所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
所以多路复用IO的特点是引入了select这样一个过程,阻塞监视多个socket,一旦有某个socket数据准备好了,则返回执行同步IO。
异步IO
用户进程发起read操作,内核会立即返回,然后内核准备数据,拷贝到用户内存,这两个阶段执行完成,内核会发一个signal给用户.
异步两个阶段都不阻塞,内核完成之后通知用户进程
信号驱动IO
信号驱动IO(signal-driven IO),使用信号机制,让内核在描述符就绪时发送SIGIO信号通知用户进程。整个过程是先通过sigaction系统调用安装一个信号处理函数。该系统调用将立即返回,用户进程继续工作,也就是说它没有被阻塞。当数据报准备好读取时,内核就为该进程产生一个SIGIO信号,我们随后可以在信号处理函数中调用recvfrom读取内核空间准备好的数据。特点:第一阶段(等待数据报到达期间)进程不被阻塞。