1. 缓冲流
1.1、缓冲流概述及原理
- 概述: 缓冲流,也叫高效流,它可以对那些基本的字节字符流进行增强,达到提高数据的读写能力。
- 原理: 创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
1.2 字节缓冲流
我们先来学习字节缓冲流是如何提高读写数据的性能的,原理如下图所示.是因为在缓冲流的底层自己封装了一个长度为8KB(8129byte)的字节数组,但是缓冲流不能单独使用,它需要依赖于原始流.
-
读数据时: 它先用原始字节输入流一次性读取8KB的数据存入缓冲流内部的数组中,再从8KB的字节数组中读取一个字节或者多个字节.
-
写数据时: 它是先把数据写到缓冲流内部的8BK的数组中,等数组存满了,再通过原始的字节输出流,一次性写到目标文件中去.
用缓冲流复制文件代码演示一下缓冲流用法:
import java.io.*;
public class BufferedInputStreamDemo {
public static void main(String[] args) {
//用字节缓冲流复制文件
FileInputStream fis = null;
BufferedInputStream bis = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
fis = new FileInputStream("文件路径");
//用字节缓冲输入流,包装字节输入流
bis = new BufferedInputStream(fis);
fos = new FileOutputStream("文件路径");
//用字节缓冲输出流,包装字节输出流
bos = new BufferedOutputStream(fos);
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//先关包在外面的(一层一层关闭) 之后会演示更好的关流方法
if (bos != null){
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bis != null){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
1.3 字符缓冲流
字符缓冲流输入:
import java.io.BufferedReader;
import java.io.FileReader;
public class BufferedReaderDemo {
public static void main(String[] args) {
try (
FileReader fr = new FileReader("文件路径");
BufferedReader br = new BufferedReader(fr)
) {
/*//经典写法:一次读1024个字符
char[] buffer = new char[1024];
int len;
while ((len = br.read(buffer)) != -1) {
String s = new String(buffer, 0, len);
System.out.println(s);
}*/
//BufferedReader独有方法:一次读一行
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
字符缓冲流输出:
import java.io.BufferedWriter;
import java.io.FileWriter;
public class BufferedWriterDemo {
public static void main(String[] args) {
try (
//创建字符输出流
FileWriter fw = new FileWriter("文件路径");
//创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(fw);
) {
bw.write("java");
//换行方法
bw.newLine();
bw.write("任重而道远");
bw.newLine();
bw.write("随便写点");
} catch (Exception e) {
e.printStackTrace();
}
}
}
2. 转换流
2.1 转换流概述及原理
转换流概述:
- Java给我们提供了另外两种流InputStreamReader,OutputStreamWriter,这两个流我们把它叫做转换流。它们可以将字节流转换为字符流,并且可以指定编码方案。
- 转换流原理:字节流+编码表。
转换流原理:
InputStreamReader类包含了一个底层输入流,可以从中读取原始字节,然后再根据指定的编码方式,将这些字节转换为字符并输出。
OutputStreamWriter从运行的程序中接收字符数据,然后使用指定的编码方式将这些字符转换为字节,再将这些字节写入底层输出流中。
2.2 输入转换流
代码演示:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
public class InputStreamReaderTest {
public static void main(String[] args) {
try (
//创建字节文件输入流
FileInputStream fis = new FileInputStream("文件路径");
//创建输入转换流
InputStreamReader isr = new InputStreamReader(fis, "GBK");
//把字符输入转换流 放入新建的缓冲流冲
BufferedReader br = new BufferedReader(isr);
) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.3 输出转换流
使用时需指定编码表,如果不指定编码表,默认会按照UTF-8形式进行转换.
代码演示:
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
public class OutputStreamWriterDemo {
public static void main(String[] args) {
try (
//创建一个文件字节输出流
FileOutputStream fos = new FileOutputStream("文件路径", true);
//把原始的字节输出流,按照指定的字符集编码转换成字符输出转换流(避免乱码)
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
//把字符输出转换流包装成缓冲流(效率更高)
BufferedWriter bw = new BufferedWriter(osw);
) {
bw.write("这里写啥都行");
} catch (Exception e) {
e.printStackTrace();
}
}
}