家人们谁懂啊!IO 流刚接触直接看懵,又是字节又是字符,缓冲、对象序列化一堆名词,像拆开一堆杂乱数据线分不清用途。今天先啃字节流这块硬骨头,用大白话 + 网络梗给你捋顺,看完再也不会分不清读写、缓冲、序列化!
一、IO 流到底是啥?内存和硬盘之间的传输管道
IO 全称输入输出流,全部放在java.io包里。 把流理解成数据线:JVM 内存是你的手机,硬盘文件、外部设备是电脑 / U 盘,数据线负责双向传数据。
三种分类方式(面试必背)
- 按流向分(以内存为参照物)
- 输入流(读):U 盘→手机,把外部文件数据读到内存,
InputStream / Reader - 输出流(写):手机→U 盘,把内存数据存进外部文件,
OutputStream / Writer
- 输入流(读):U 盘→手机,把外部文件数据读到内存,
- 按传输单位分
- 字节流:以 byte 字节为单位,全能选手!图片、视频、压缩包、文档全都能操作,后缀
InputStream/OutputStream - 字符流:以字符 char 为单位,专精 txt、java、html 纯文本,处理音视频直接翻车,后缀
Reader/Writer
- 字节流:以 byte 字节为单位,全能选手!图片、视频、压缩包、文档全都能操作,后缀
- 按功能分
- 节点流:原生裸数据线,只能基础读写,直接绑定文件(File 开头)
- 过滤流:带快充缓冲、特殊功能的升级数据线,套在节点流外面增强性能
二、字节流顶层父类(抽象类,不能 new)
InputStream:所有字节输入流爸爸,核心动作read()读数据OutputStream:所有字节输出流爸爸,核心动作write()写数据
三、字节节点流:FileInputStream / FileOutputStream(开发核心)
相当于直接插文件的原生数据线,操作本地文件读写。
1. FileOutputStream 文件字节输出流(写文件)
三种构造方法用法,分绝对路径、相对路径、追加 / 覆盖模式:
new FileOutputStream("E:/test/a.txt")绝对路径- 文件不存在自动新建;但上级文件夹不存在直接报 FileNotFoundException,系统找不到路径
new FileOutputStream("a.txt")相对路径,项目根目录找文件new FileOutputStream("c.txt",false)第二个布尔参数:true 追加内容,false 覆盖原有内容(默认覆盖)
三个写方法:
write(int n):写入单个字节write(byte[] bs):一次性写入整个字节数组write(byte[] bs,int off,int len):数组截取一段写入close():用完必须关流!释放系统资源,不关会资源泄漏
2. FileInputStream 文件字节输入流(读文件)
构造:new FileInputStream("file/d.txt")重点:文件不存在不会自动创建,直接抛找不到文件异常!三个读方法:
read():一次读 1 个字节,读到文件末尾返回 - 1(循环读取标配)
java运行
FileInputStream fis = new FileInputStream("test.txt"); while(true){ int n = fis.read(); if(n == -1) break; System.out.print((char)n); }read(byte[] bs):批量读取字节进数组,返回本次读到的长度,末尾返回 - 1read(byte[] bs,int off,int len):限定数组区间读取
小总结
File 输入输出流组合,就是文件复制、上传下载底层原理,所有文件拷贝工具底层全靠它俩。
四、字节过滤流:功能升级的快充数据线
1. Buffered 缓冲流:BufferedInputStream / BufferedOutputStream
痛点:原生节点流每次读写都访问硬盘,频繁读写巨卡,像反复插拔 U 盘传文件。 缓冲流自带内存缓冲区,攒满一整块数据再一次性读写,大幅减少磁盘访问,速度起飞。 关键两个方法区别:
flush():强制把缓冲区剩余数据刷进文件,缓冲区清空,流还能继续用close():关流前自动执行 flush,缓冲区清空,流直接报废不能再操作 触发自动刷盘:缓冲区装满时自动写入磁盘。
2. Data 数据流:DataInputStream / DataOutputStream
专门读写 8 大基本数据类型,存数字、布尔值专用,配套读写,顺序不能乱。 方法:writeInt()/writeByte()/readInt()/readBoolean()
3. 对象流:ObjectInputStream / ObjectOutputStream(面试重中之重)
主打对象序列化:把 Java 对象丢进流,存到文件 / 网络传输,相当于给人物打包快递。
- 核心方法
writeObject(Object obj):序列化对象写入文件Object readObject():从文件读取还原对象,读到文件尾抛EOFException
- 序列化硬性规则(踩坑高频点)
- 要序列化的类必须实现 Serializable 标记接口,不实现直接报 NotSerializable 不可序列化异常
transient修饰的字段会被直接忽略,不参与序列化(比如密码、临时缓存数据)- 对象里包含自定义类成员,成员类也必须实现 Serializable
- 集合存自定义对象,自定义类同样要实现该接口
- 对比 PrintWriter:Object 流是完整对象打包;PrintWriter 只调用 toString 存文字,不需要序列化接口
本期小结
字节流是 IO 万能工具,不管什么格式文件都能操作;节点流做基础读写,缓冲流提速,数据流存基础类型,对象流打包对象序列化。下一篇咱们拆解字符流、桥转换流、File 文件工具类,搞定文本读写、乱码、文件夹递归遍历!