下方,标红为重点,蓝底为掌握。

image.png

流的分类(重点):1.从存取方向上讲:所有流被分为输入流和输出流。2.从编码上讲,流分为字节流和字符流。3. 从类的实现上讲:节点流(或称文件流)分为4个基类(即,(输入 or 输出) & (字节 or 字符)共4种组合),而这4个基类的子类属于处理流(如缓冲流、转换流、等等)。

image.png

image.png

“字节流、字符流、缓冲流”(个人观点)

  • 关于字节流和字符流:从机器的角度讲,字节流就够了,但是对于人而言,字符是字节编码而来的,为了适应这种编码机制,专门提供了处理字符数据的字符流。
  • 缓冲流并非字节流和字符流的并行概念,它是对字节流和字符流的“赋能”(即继承自节点流,属于处理流的一种),它提供一个额外的缓冲区(默认8kb)及配套方法,增强了读写速度。所以在开发中,一般都用字节缓冲流、字符缓冲流。

    IO流的实现代码一般4个步骤:

    image.png
    image.png

拷贝文件:文件流(节点流) vs 缓冲流(更快)

如下代码的结论:
fileStream copy 完成.平均耗时:256
bufferStream copy 完成.平均耗时:76

可见,缓冲流更快,关键原因其实它内部额外提供来一个比较大的缓冲区: buffer流额外提供了默认大小为DEFAULT_BUFFER_SIZE=1024*8 (即8kb) 的缓冲区。
注意:下方代码里也定义了 byte[] bbuf = new byte[1024] 来读写字节数据,也是算是简单的缓冲区,所以如果将文件流这里的bbuf设置大一些,文件流的速度也会很快。 但是注意,缓冲流中的缓冲区额外还有 flush()方法来刷新缓冲区等机制。

代码

  1. package xj.java;
  2. import org.junit.jupiter.api.Test;
  3. import java.io.*;
  4. /**
  5. * @author jia
  6. * @create 2021-12-01 6:16 下午
  7. */
  8. public class CopyFile {
  9. @Test
  10. public void copyTest(){
  11. String src = "/Users/xujia/Desktop/bigdata/1.尚硅谷大数据学科--核心基础/尚硅谷Java核心基础/v.avi";
  12. String des = "/Users/xujia/Desktop/bigdata/1.尚硅谷大数据学科--核心基础/尚硅谷Java核心基础/v-filecopy.avi";
  13. String bufferdes = "/Users/xujia/Desktop/bigdata/1.尚硅谷大数据学科--核心基础/尚硅谷Java核心基础/v-buffercopy.avi";
  14. long a;
  15. long file_total = 0;
  16. long buffer_total = 0;
  17. int times = 10;
  18. for (int i=0 ; i < times;i++){
  19. a = System.currentTimeMillis();
  20. filecopy(src,des);
  21. file_total += (System.currentTimeMillis() - a);
  22. a = System.currentTimeMillis();
  23. buffercopy(src,bufferdes);
  24. buffer_total += (System.currentTimeMillis() - a);
  25. }
  26. System.out.println("fileStream copy 完成.平均耗时:" + (file_total / times));
  27. System.out.println("bufferStream copy 完成.平均耗时:" + (buffer_total / times));
  28. }
  29. public static void buffercopy(String src,String des){
  30. BufferedInputStream bis = null;
  31. BufferedOutputStream bos = null;
  32. try {
  33. bis = new BufferedInputStream(new FileInputStream(src));
  34. bos = new BufferedOutputStream(new FileOutputStream(des));
  35. byte[] bbuf = new byte[1024];
  36. int bbuf_size = 0;
  37. while ((bbuf_size = bis.read(bbuf)) != -1){
  38. bos.write(bbuf,0,bbuf_size);
  39. }
  40. } catch (IOException e) {
  41. e.printStackTrace();
  42. } finally {
  43. try {
  44. if (bis != null)
  45. bis.close();
  46. if (bos != null)
  47. bos.close();
  48. } catch (IOException e) {
  49. e.printStackTrace();
  50. }
  51. }
  52. }
  53. public static void filecopy(String src,String des){
  54. FileInputStream fis = null;
  55. FileOutputStream fos = null;
  56. try {
  57. // make stream
  58. fis = new FileInputStream(src);
  59. fos = new FileOutputStream(des);
  60. // copy
  61. byte[] bbuf = new byte[1024];
  62. int bbuf_size = 0;
  63. while ((bbuf_size = fis.read(bbuf)) != -1){
  64. fos.write(bbuf,0,bbuf_size);
  65. }
  66. } catch (IOException e) {
  67. e.printStackTrace();
  68. } finally {
  69. try {
  70. if (fis != null)
  71. fis.close();
  72. if (fos != null)
  73. fos.close();
  74. } catch (IOException e) {
  75. e.printStackTrace();
  76. }
  77. }
  78. }
  79. }

字符缓冲流: 在读写方式上,对文本数据做了补充,比如readLine()方法。

image.png

转换流: 属于字符流,它提供字节流与字符流之间的转换

image.png
image.png
image.png
image.png

对象流: 1.(反)序列化: 对象与字节数据的转换。2. 类可序列化3点要求:1.实现Serializable接口、 2.并提供static final long serialVersionUID属性、3. 内部属性满足可序列化、3. 开发上,一般不直接序列化对象为字节数据,而是先序列化为String,并用json格式来保存字符串。

关于序列化中的 serialVersionUID属性: 可唯一标识类,即使在序列化后对类进行了修改,那么反序列化依然能进行。反之,如果不提供该属性,虽然序列化依然可进行,一旦类进行了修改,则反序列化失败。

image.png

image.png

(代码)将Person对象序列化

  1. package xj.java;
  2. import org.junit.jupiter.api.Test;
  3. import java.io.*;
  4. /**
  5. * @author jia
  6. * @create 2021-12-01 10:46 下午
  7. */
  8. public class Serialize {
  9. @Test
  10. public void SerialTest(){
  11. Person person = new Person("jia", 12306,1000);
  12. OutputStream os = null;
  13. ObjectOutputStream objectOutputStream = null;
  14. // 1. 序列化
  15. try {
  16. os = new FileOutputStream("person.bin");
  17. objectOutputStream = new ObjectOutputStream(os);
  18. objectOutputStream.writeObject(person);
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. } finally {
  22. if (objectOutputStream != null){
  23. try {
  24. objectOutputStream.close();
  25. } catch (IOException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }
  30. // 2. 反序列化
  31. InputStream is = null;
  32. Person person2 = null;
  33. ObjectInputStream objectInputStream = null;
  34. try {
  35. is = new FileInputStream("person.bin");
  36. objectInputStream = new ObjectInputStream(is);
  37. try {
  38. person2 = (Person) objectInputStream.readObject();
  39. } catch (ClassNotFoundException e) {
  40. e.printStackTrace();
  41. }
  42. } catch (IOException e) {
  43. e.printStackTrace();
  44. } finally {
  45. try {
  46. if (objectInputStream != null)
  47. objectInputStream.close();
  48. } catch (IOException e) {
  49. e.printStackTrace();
  50. }
  51. }
  52. // 测试 原对象和反序列化对象
  53. System.out.println("原对象: " + person);
  54. System.out.println("反序列化对象: " + person2);
  55. }
  56. }
  57. class Acount implements Serializable{
  58. @java.io.Serial
  59. private static final long serialVersionUID = -6849794470712367710L;
  60. float balance;
  61. public Acount(float balance) {
  62. this.balance = balance;
  63. }
  64. @Override
  65. public String toString() {
  66. return "balance=" + balance ;
  67. }
  68. }
  69. class Person implements Serializable {
  70. // 1. 实现Serializable接口
  71. // 2. 唯一化标识
  72. @java.io.Serial
  73. private static final long serialVersionUID = -6821941230754667710L;
  74. String name;
  75. int carId;
  76. Acount acount; // 3. 所有属性要可序列化
  77. public Person(String name, int carId, float acount) {
  78. this.name = name;
  79. this.carId = carId;
  80. this.acount = new Acount(acount);
  81. }
  82. @Override
  83. public String toString() {
  84. return "Person{" +
  85. "name='" + name + '\'' +
  86. ", carId=" + carId +
  87. ", acount=" + acount +
  88. '}';
  89. }
  90. }

随机存取文件流: 1.继承Object类,2.同时实现DataInput、DataOutput接口(由构造器的mode参数控制),3.文件记录指针:long getFilePointer(), void seek(long pos)。

image.png
image.png

seek: 比如实现多线程断点下载。

image.png

方法补充:”abc”.getBytes()

Java NIO(先了解,以后再展开): 1. jdk1.4推出的(Non-Blocking IO)。2. NIO面向缓冲区的(原IO面向流)、基于通道的IO操作。3. NIO有两套,分别针对标准IO、网络编程。4. jdk1.7推出NIO.2。

image.png

  • NIO.2 : 引入Path类替代原Files类,提供Files工具类来操作文件或目录

image.png
image.png
image.png