IO流简介
IO流就是将数据以字节或者字符的形式进行传输,在java中主要用于磁盘的读写和网络请求的输入和输出。Java提供许多操作IO流的类,顶级抽象类有四个。Reader:字符输入流 Writer:字符输出流 InputStream:字节输入流 OutputStream:字节输出流。其中输入和输出是针对运行在内存中的程序而言。字符流其实也是通过字节流来实现的,只是在字节流上加了一步对于编码格式的处理,将字节转化为了字符,转化时默认的编码格式是UTF-8。也可以指定编码格式。下面列举两个列子。
文件流
对于文件的操作IO流有提供FileInputStream,FileOutputStream两个类来实现,而对于纯文本文件的操作IO流提供了FileReader和FileWriter两个类来实现。两者使用方式一样,只是字符流可以直接对字符进行操作,字节流必须把字符转换成字节才能操作,因为字符流里面帮我们把转换这步操作通过转换流(InuputStreamRead,OutputStreamWriter)完成了。具体使用方法如下。
public static void main(String[] args) throws IOException {
String a = "磁盘文件的输入和输出操作";
byte[] b = a.getBytes();
File file = new File("D:\\文件操作练习\\测试.txt");
if (file.exists()) {
System.out.println("文件已经存在");
} else {
if (!file.getParentFile().mkdirs()) {
System.out.println("创建文件夹失败");
}
if (!file.createNewFile()) {
System.out.println("创建文件失败");
}
}
FileOutputStream fileOutputStream = new FileOutputStream(file,true);
FileWriter fileWriter = new FileWriter(file,true);
fileWriter.write(a);
fileOutputStream.write(b);
fileOutputStream.close();
fileWriter.close();
String dest = "D:\\文件操作练习1\\测试1.txt";
copy(file.getAbsolutePath(),dest);
}
public static void copy(String src,String dest) throws IOException {
File file = new File(dest);
if (file.exists()) {
System.out.println("文件已经存在");
} else {
if (!file.getParentFile().mkdirs()) {
System.out.println("创建文件夹失败");
}
if (!file.createNewFile()) {
System.out.println("创建文件失败");
}
}
byte[] b = new byte[1024];
FileInputStream fileInputStream = new FileInputStream(src);
FileOutputStream fileOutputStream = new FileOutputStream(file);
while (fileInputStream.read(b)!= -1){
fileOutputStream.write(b);
}
FileReader fileReader = new FileReader(src);
FileWriter fileWriter = new FileWriter(file);
char[] chars = new char[1024];
while(fileReader.read(chars) != -1){
fileWriter.write(chars);
}
fileWriter.close();
fileReader.close();
fileInputStream.close();
fileOutputStream.close();
}
高效缓冲流
和普通的IO流一样,高效缓冲流也有四个实现类BufferedInputStream,BufferedOutputStream,BufferedRead,BufferedReader
高效缓冲流会建立对应的缓冲区,一次IO操作就会把大量数据先放入缓冲区中,之后程序就会直接操作缓冲区中的数据,而不需要再进行IO操作。使用方法和之前文件缓冲流没有区别,只有字符流方法中多了两个方法,读一行文件,写一行文件。需要注意的是当缓冲流写文件时,如果没有关闭流,是读不到当前正在写入的数据的。
public static void main(String[] args) throws IOException {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("D:\\文件操作练习\\测试.txt"));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("D:\\文件操作练习\\测试.txt"));
BufferedReader bufferedReader = new BufferedReader(new FileReader("D:\\文件操作练习\\测试.txt"));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("D:\\文件操作练习\\测试.txt",true));
String a = "aaa,bbb,ccc,ddd,eee,fff,ggg";
String[] array = a.split(",");
for(String s : array){
bufferedWriter.write(s);
bufferedWriter.newLine();
}
bufferedWriter.close();
String s ;
while ((s=bufferedReader.readLine()) != null){
System.out.println("读取一行数据"+s);
}
bufferedReader.close();
}
五种IO模型
阻塞io:线程会一直等待内核准备好数据,准备好后线程再去获取数据(从内核空间拷贝到用户空间)
非阻塞io:内核如果没有准备好数据会直接返回,所以需要线程一直调用,准备好后线程再去获取数据(从内核空间拷贝到用户空间)
多路复用io:使用一个线程轮询监听多个请求,数据准备好后由监听线程通知应用线程,未准备好就阻塞监听线程。最后应用线程再去获取数据(从内核空间拷贝到用户空间)
信号驱动io: 系统注册一个信号处理函数(回调函数),在数据准备好后由内核主动通知应用线程,应用线程再去获取数据(从内核空间拷贝到用户空间)
异步io:以上四种io模型都需要先发送请求使数据在内核空间中准备好,再获取从内核空间获取数据到应用线程。而异步io只需发起一次请求后直接使用数据
BIO:
面向字节和字符流的同步阻塞io,每次io请求都会创建一个线程处理.
NIO:
由缓冲区(Buffer)和通道(Channel)以及选择器(selectors)实现,是面向缓冲区的同步非阻塞io,
AIO
异步非阻塞