概述
- 为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区。
- 缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:
字节缓冲流:BufferedInputStream 和 BufferedOutputStream
字符缓冲流:BufferedReader 和 BufferedWriter
使用说明
- 当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区
- 当使用BufferedInputStream读取字节文件时,BufferedInputStream会一次性从文件中读取8192个字节(8Kb)存在缓冲区中,直到缓冲区装满了,才重新从文件中读取下一个8192个字节数组。
- 向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。使用方法 flush()可以强制将缓冲区的内容全部写入输出流
- 关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也会相应关闭内层节点流
- flush()方法的使用:手动将buffer中内容写入文件
- 如果是带缓冲区的流对象的close()方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再写出

代码实现
/*字节缓冲流:BufferedInputStream 和 BufferedOutputStream实现非文本文件的复制*/@Testpublic void BufferedStreamTest() throws FileNotFoundException {BufferedInputStream bis = null;BufferedOutputStream bos = null;try {//1.造文件File srcFile = new File("爱情与友情.jpg");File destFile = new File("爱情与友情3.jpg");//2.造流//2.1 造节点流FileInputStream fis = new FileInputStream((srcFile));FileOutputStream fos = new FileOutputStream(destFile);//2.2 造缓冲流bis = new BufferedInputStream(fis);bos = new BufferedOutputStream(fos);//3.复制的细节:读取、写入byte[] buffer = new byte[10];int len;while((len = bis.read(buffer)) != -1){bos.write(buffer,0,len);// bos.flush();//刷新缓冲区}} catch (IOException e) {e.printStackTrace();} finally {//4.资源关闭//要求:先关闭外层的流,再关闭内层的流if(bos != null){try {bos.close();} catch (IOException e) {e.printStackTrace();}}if(bis != null){try {bis.close();} catch (IOException e) {e.printStackTrace();}}//说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.// fos.close();// fis.close();}}
/*使用字符缓冲流BufferedReader和BufferedWriter实现文本文件的复制*/@Testpublic void testBufferedReaderBufferedWriter(){BufferedReader br = null;BufferedWriter bw = null;try {//创建文件和相应的流br = new BufferedReader(new FileReader(new File("dbcp.txt")));bw = new BufferedWriter(new FileWriter(new File("dbcp1.txt")));//读写操作//方式一:使用char[]数组// char[] cbuf = new char[1024];// int len;// while((len = br.read(cbuf)) != -1){// bw.write(cbuf,0,len);// // bw.flush();// }//方式二:使用StringString data;while((data = br.readLine()) != null){//方法一:// bw.write(data + "\n");//data中不包含换行符//方法二:bw.write(data);//data中不包含换行符bw.newLine();//提供换行的操作}} catch (IOException e) {e.printStackTrace();} finally {//关闭资源if(bw != null){try {bw.close();} catch (IOException e) {e.printStackTrace();}}if(br != null){try {br.close();} catch (IOException e) {e.printStackTrace();}}}}}
练习题
//取文本上每个字符出现的次数// 提示:遍历文本的每一个字符;字符及出现的次数保存在Map中;将Map中数据//写入文件public void test() {BufferedReader reader = null;BufferedWriter writer = null;try {reader = new BufferedReader(new FileReader("world.txt"));writer = new BufferedWriter(new FileWriter("count.txt"));Map<Character, Integer> save = new HashMap<>();int ch;while ((ch = reader.read()) != -1) {char key = (char) ch;if (save.get(key) != null) {save.put(key, save.get(key) + 1);} else {save.put(key, 1);}}Set<Map.Entry<Character, Integer>> entries = save.entrySet();Iterator<Map.Entry<Character, Integer>> iterator = entries.iterator();while (iterator.hasNext()) {Map.Entry<Character, Integer> next = iterator.next();Character key = next.getKey();Integer value = next.getValue();if ('\t' == key) {writer.write("Tab键" + "=" + value + "\n");} else if ('\n' == key) {writer.write("换行" + "=" + value + "\n");} else if ('\r' == key) {writer.write("回车" + "=" + value + "\n");} else if (' ' == key) {writer.write("空格" + "=" + value + "\n");} else {writer.write(key + "=" + value + "\n");}}} catch (IOException e) {e.printStackTrace();} finally {if (reader != null) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}if (writer != null) {try {writer.close();} catch (IOException e) {e.printStackTrace();}}}}}
