为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区
image.png

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

image.png

1、缓冲流(字节型)实现非文本文件的复制

  1. import org.junit.Test;
  2. import java.io.*;
  3. /**
  4. * 处理流之一:缓冲流的使用
  5. *
  6. * 1.缓冲流:
  7. * BufferedInputStream
  8. * BufferedOutputStream
  9. * BufferedReader
  10. * BufferedWriter
  11. */
  12. public class BufferedTest {
  13. /**
  14. * 实现非文本文件的复制
  15. */
  16. @Test
  17. public void BufferedStreamTest(){
  18. BufferedInputStream bis = null;
  19. BufferedOutputStream bos = null;
  20. try {
  21. //1.造文件
  22. File srcFile = new File("爱情与友情.jpg");
  23. File destFile = new File("爱情与友情3.jpg");
  24. //2.造流
  25. //2.1 造节点流
  26. FileInputStream fis = new FileInputStream((srcFile));
  27. FileOutputStream fos = new FileOutputStream(destFile);
  28. //2.2 造缓冲流
  29. bis = new BufferedInputStream(fis);
  30. bos = new BufferedOutputStream(fos);
  31. //3.复制的细节:读取、写入
  32. byte[] buffer = new byte[10];
  33. int len;
  34. while((len = bis.read(buffer)) != -1){
  35. bos.write(buffer,0,len);
  36. // bos.flush();//刷新缓冲区
  37. }
  38. } catch (IOException e) {
  39. e.printStackTrace();
  40. } finally {
  41. //4.资源关闭
  42. //要求:先关闭外层的流,再关闭内层的流
  43. if(bos != null){
  44. try {
  45. bos.close();
  46. } catch (IOException e) {
  47. e.printStackTrace();
  48. }
  49. }
  50. if(bis != null){
  51. try {
  52. bis.close();
  53. } catch (IOException e) {
  54. e.printStackTrace();
  55. }
  56. }
  57. //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.
  58. // fos.close();
  59. // fis.close();
  60. }
  61. }
  62. }

2、缓冲流与节点流读写速度对比

  1. import org.junit.Test;
  2. import java.io.*;
  3. /**
  4. * 处理流之一:缓冲流的使用
  5. *
  6. * 1.缓冲流:
  7. * BufferedInputStream
  8. * BufferedOutputStream
  9. * BufferedReader
  10. * BufferedWriter
  11. *
  12. * 2.作用:提供流的读取、写入的速度
  13. * 提高读写速度的原因:内部提供了一个缓冲区
  14. *
  15. * 3. 处理流,就是“套接”在已有的流的基础上。
  16. *
  17. */
  18. public class BufferedTest {
  19. //实现文件复制的方法
  20. public void copyFileWithBuffered(String srcPath,String destPath){
  21. BufferedInputStream bis = null;
  22. BufferedOutputStream bos = null;
  23. try {
  24. //1.造文件
  25. File srcFile = new File(srcPath);
  26. File destFile = new File(destPath);
  27. //2.造流
  28. //2.1 造节点流
  29. FileInputStream fis = new FileInputStream((srcFile));
  30. FileOutputStream fos = new FileOutputStream(destFile);
  31. //2.2 造缓冲流
  32. bis = new BufferedInputStream(fis);
  33. bos = new BufferedOutputStream(fos);
  34. //3.复制的细节:读取、写入
  35. byte[] buffer = new byte[1024];
  36. int len;
  37. while((len = bis.read(buffer)) != -1){
  38. bos.write(buffer,0,len);
  39. }
  40. } catch (IOException e) {
  41. e.printStackTrace();
  42. } finally {
  43. //4.资源关闭
  44. //要求:先关闭外层的流,再关闭内层的流
  45. if(bos != null){
  46. try {
  47. bos.close();
  48. } catch (IOException e) {
  49. e.printStackTrace();
  50. }
  51. }
  52. if(bis != null){
  53. try {
  54. bis.close();
  55. } catch (IOException e) {
  56. e.printStackTrace();
  57. }
  58. }
  59. //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.
  60. // fos.close();
  61. // fis.close();
  62. }
  63. }
  64. @Test
  65. public void testCopyFileWithBuffered(){
  66. long start = System.currentTimeMillis();
  67. String srcPath = "C:\\Users\\29433\\Desktop\\book.flv";
  68. String destPath = "C:\\Users\\29433\\Desktop\\book1.flv";
  69. copyFileWithBuffered(srcPath,destPath);
  70. long end = System.currentTimeMillis();
  71. System.out.println("复制操作花费的时间为:" + (end - start));//1
  72. }
  73. }

3、缓冲流(字符型)实现文本文件的复制

  1. import org.junit.Test;
  2. import java.io.*;
  3. public class BufferedTest {
  4. /**
  5. * 使用BufferedReader和BufferedWriter实现文本文件的复制
  6. */
  7. @Test
  8. public void test4(){
  9. BufferedReader br = null;
  10. BufferedWriter bw = null;
  11. try {
  12. //创建文件和相应的流
  13. br = new BufferedReader(new FileReader(new File("dbcp.txt")));
  14. bw = new BufferedWriter(new FileWriter(new File("dbcp1.txt")));
  15. //读写操作
  16. //方式一:使用char[]数组
  17. // char[] cbuf = new char[1024];
  18. // int len;
  19. // while((len = br.read(cbuf)) != -1){
  20. // bw.write(cbuf,0,len);
  21. // // bw.flush();
  22. // }
  23. //方式二:使用String
  24. String data;
  25. while((data = br.readLine()) != null){
  26. //方法一:
  27. // bw.write(data + "\n");//data中不包含换行符
  28. //方法二:
  29. bw.write(data);//data中不包含换行符
  30. bw.newLine();//提供换行的操作
  31. }
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. } finally {
  35. //关闭资源
  36. if(bw != null){
  37. try {
  38. bw.close();
  39. } catch (IOException e) {
  40. e.printStackTrace();
  41. }
  42. }
  43. if(br != null){
  44. try {
  45. br.close();
  46. } catch (IOException e) {
  47. e.printStackTrace();
  48. }
  49. }
  50. }
  51. }
  52. }

4、缓冲流课后练习

image.png

  1. package git;
  2. import org.junit.Test;
  3. import java.io.FileInputStream;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. public class PicTest {
  7. //图片的加密
  8. @Test
  9. public void test() {
  10. FileInputStream fis = null;
  11. FileOutputStream fos = null;
  12. try {
  13. fis = new FileInputStream("爱情与友情.jpg");
  14. fos = new FileOutputStream("爱情与友情secret.jpg");
  15. byte[] buffer = new byte[20];
  16. int len;
  17. while ((len = fis.read(buffer)) != -1) {
  18. //字节数组进行修改
  19. //错误的
  20. // for(byte b : buffer){
  21. // b = (byte) (b ^ 5);
  22. // }
  23. //正确的
  24. for (int i = 0; i < len; i++) {
  25. buffer[i] = (byte) (buffer[i] ^ 5);
  26. }
  27. fos.write(buffer, 0, len);
  28. }
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. } finally {
  32. if (fos != null) {
  33. try {
  34. fos.close();
  35. } catch (IOException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. if (fis != null) {
  40. try {
  41. fis.close();
  42. } catch (IOException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. }
  47. }
  48. //图片的解密
  49. @Test
  50. public void test2() {
  51. FileInputStream fis = null;
  52. FileOutputStream fos = null;
  53. try {
  54. fis = new FileInputStream("爱情与友情secret.jpg");
  55. fos = new FileOutputStream("爱情与友情4.jpg");
  56. byte[] buffer = new byte[20];
  57. int len;
  58. while ((len = fis.read(buffer)) != -1) {
  59. //字节数组进行修改
  60. //错误的
  61. // for(byte b : buffer){
  62. // b = (byte) (b ^ 5);
  63. // }
  64. //正确的
  65. for (int i = 0; i < len; i++) {
  66. buffer[i] = (byte) (buffer[i] ^ 5);
  67. }
  68. fos.write(buffer, 0, len);
  69. }
  70. } catch (IOException e) {
  71. e.printStackTrace();
  72. } finally {
  73. if (fos != null) {
  74. try {
  75. fos.close();
  76. } catch (IOException e) {
  77. e.printStackTrace();
  78. }
  79. }
  80. if (fis != null) {
  81. try {
  82. fis.close();
  83. } catch (IOException e) {
  84. e.printStackTrace();
  85. }
  86. }
  87. }
  88. }
  89. }