缓冲流顾名思义就是为输入输出流提供缓冲功能,将数据存储在缓冲区内,然后再针对缓冲区中的内容进行read和write,因为内存的读写速度要超过硬盘读取速度10倍以上,所以缓冲流可以大大的提高我们的工作效率,Java 提供了几个缓冲流,它们分别是:
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
BufferedInputStream 内部有一个默认大小为 8192 字节的字节数组,当我们调用其read方法读取输入流时,BufferedInputStream 会将该底层输入流的数据分批读取到缓冲区中。每当缓冲区中的数据被读完,输入流会继续填充到缓冲区中,直到读完输入流。
我们也可以自己指定缓冲区大小,但一般使用默认即可。
BufferedInputStream(InputStream in)
创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
BufferedInputStream(InputStream in, int size)
创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
available()
返回可以从此输入流读取(或跳过)、且不受此输入流接下来的方法调用阻塞的估计字节数。
close()
关闭此输入流并释放与该流关联的所有系统资源。
mark(int readlimit)
参见 InputStream 的 mark 方法的常规协定。
markSupported()
测试此输入流是否支持 mark 和 reset 方法。
read()
参见 InputStream 的 read 方法的常规协定。
read(byte[] b, int off, int len)
从此字节输入流中给定偏移量处开始将各字节读取到指定的 byte 数组中。
reset()
参见 InputStream 的 reset 方法的常规协定。
skip(long n)
参见 InputStream 的 skip 方法的常规协定。
该对象中同样有一个大小为 8192 字节长度的字节数组为缓冲区,输出时候会直接输出缓冲区中的内容,然后再将数据写入到缓冲区中,如果写出的数据大于缓冲区,会将缓冲区数据写出然后再直接将写出数据写出。
BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out, int size)
创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
flush()
刷新此缓冲的输出流。
write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流。
write(int b)
将指定的字节写入此缓冲的输出流。
public class BufferedTest {
private BufferedInputStream bis;
private BufferedOutputStream bos;
private FileInputStream fis;
private FileOutputStream fos;
public static void main(String[] args) {
new BufferedTest().testBufferCopyAudioFile();
new BufferedTest().testCopyAudioFile();
}
/**
* 直接使用文件输入输出流复制文件
*/
private void testCopyAudioFile() {
long time = System.currentTimeMillis();
try {
fis = new FileInputStream(new File("D:\\李宗盛 - 山丘.wav"));
fos = new FileOutputStream(new File("D:\\李宗盛 - 山丘 - COPY.wav"));
int length = 0;
byte[] arr = new byte[1024];
while ((length = fis.read(arr)) != -1) {
fos.write(arr, 0, length);
fos.flush();
}
System.out.println("直接复制共耗时: "
+ (System.currentTimeMillis() - time) + " 毫秒");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 使用缓冲流包装文件输入输出流复制文件
*/
private void testBufferCopyAudioFile() {
long time = System.currentTimeMillis();
try {
bis = new BufferedInputStream(new FileInputStream(new File(
"D:\\李宗盛 - 山丘.wav")));
bos = new BufferedOutputStream(new FileOutputStream(new File(
"D:\\李宗盛 - 山丘 - COPY - BUFFER.wav")));
int length = 0;
byte[] arr = new byte[1024];
while ((length = bis.read(arr)) != -1) {
bos.write(arr, 0, length);
bos.flush();
}
System.out.println("利用缓冲流共耗时: "
+ (System.currentTimeMillis() - time) + " 毫秒");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (bis != null) {
bis.close();
}
if (bos != null) {
bos.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
缓冲字符流从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。其内部同样维护了一个默认大小为 8192 的 char 数组用来缓存读取到的数据。
我们也可以指定缓冲区大小,但一般使用默认即可。
BufferedReader 提供了 readLine 方法来读取一个文本行。如果遇到换行 \n
、回车 \r
或回车后直接跟着换行。
BufferedReader(Reader in)
创建一个使用默认大小输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz)
创建一个使用指定大小输入缓冲区的缓冲字符输入流。
close()
关闭该流并释放与之关联的所有资源。
mark(int readAheadLimit)
标记流中的当前位置。
markSupported()
判断此流是否支持 mark() 操作(它一定支持)。
read()
读取单个字符。
read(char[] cbuf, int off, int len)
将字符读入数组的某一部分。
readLine()
读取一个文本行。
ready()
判断此流是否已准备好被读取。
reset()
将流重置到最新的标记。
skip(long n)
跳过字符。
将文本写入字符输出流,对象包含一个默认大小为 8192 的字符数组作为缓存区,用来缓冲需要写出的数据。缓冲区的大小可以自己定义,但一般使用默认即可。
BufferedWriter 提供了 newLine 方法,它使用平台自己的行分隔符概念,并非所有平台都使用新行符\n
来终止各行。
BufferedWriter(Writer out)
创建一个使用默认大小输出缓冲区的缓冲字符输出流。
BufferedWriter(Writer out, int sz)
创建一个使用给定大小输出缓冲区的新缓冲字符输出流。
close()
关闭此流,但要先刷新它。
flush()
刷新该流的缓冲。
newLine()
写入一个行分隔符。
write(char[] cbuf, int off, int len)
写入字符数组的某一部分。
write(int c)
写入单个字符。
write(String s, int off, int len)
写入字符串的某一部分。
public class BufferedTest {
private BufferedReader bufReader;
private BufferedWriter bufWriter;
private FileReader reader;
private FileWriter writer;
public static void main(String[] args) {
new BufferedTest().testCopyTextFile();
new BufferedTest().testBuffCopyTextFile();
}
private void testCopyTextFile() {
long time = System.currentTimeMillis();
try {
reader = new FileReader(new File("D:\\射雕英雄传.txt"));
writer = new FileWriter(new File("D:\\射雕英雄传 - copy.txt"));
char[] arr = new char[1024];
int length = 0;
while ((length = reader.read(arr)) != -1) {
writer.write(arr, 0, length);
writer.flush();
}
System.out.println("直接复制共耗时: "
+ (System.currentTimeMillis() - time) + " 毫秒");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void testBuffCopyTextFile() {
long time = System.currentTimeMillis();
try {
bufReader = new BufferedReader(new FileReader(new File(
"D:\\射雕英雄传.txt")));
bufWriter = new BufferedWriter(new FileWriter(new File(
"D:\\射雕英雄传 - copy - buf.txt")));
// int length = 0;
// char[] arr = new char[1024];
// while ((length = bufReader.read(arr)) != -1) {
// bufWriter.write(arr, 0, length);
// bufWriter.flush();
// }
String line = "";
while ((line = bufReader.readLine()) != null) {
bufWriter.write(line);
bufWriter.newLine();
// bufWriter.flush();
}
System.out.println("缓冲流复制共耗时: "
+ (System.currentTimeMillis() - time) + " 毫秒");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (bufReader != null) {
bufReader.close();
}
if (bufWriter != null) {
bufWriter.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}