ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Java IO 完整学习笔记|字节流、字符流、缓冲流、资源关闭全梳理

2026/9/3 5:24:26 拓冰建站 浏览量
Java IO 完整学习笔记|字节流、字符流、缓冲流、资源关闭全梳理 一、IO流整体体系Java IO两大分支字节流、字符流所有流都实现AutoCloseable接口支持try‑with‑resources自动关闭。分类输入读输出写处理单元字节流InputStreamOutputStreambyte 字节字符流ReaderWriterchar 字符1. 字节流万能二进制流父类InputStream/OutputStream常用实现FileInputStream、FileOutputStream✅ 适用所有文件图片、视频、压缩包、文档。直接操作原始二进制不会做编码转换。核心API//读返回int-1代表读到文件末尾 int read(); //读取1个字节 int read(byte[] buffer); //批量读到字节数组返回读到字节数 //写 void write(int b); //写单个字节 void write(byte[] b); //写整个字节数组 void write(byte[] b,int off,int len); //数组指定范围写入⚠️重点read()返回int而不是byte字节范围‑128~127如果读到字节0xFF强转byte等于‑1会和文件结束标记‑1冲突。所以用int接收高24位补0用‑1代表流结束。FileOutputStream构造第二个参数true追加写入不传/false覆盖原文件。2. 字符流专门处理文本父类Reader/Writer常用实现FileReader、FileWriter✅适用纯文本文件.txt、.java、.md ❌禁止处理图片视频等二进制文件会直接损坏文件。底层本质字符流 字节流 编码解码把字节按照字符集转成char。核心APIint read(); //读1个字符返回‑1结束 int read(char[] cbuf); //批量读到字符数组 void write(int c); void write(char[] cbuf); void write(String str);⚠️字符流自带内存缓冲区 数据先写到内存缓冲区没有调用flush()或者close()数据不会落到磁盘会出现文件空白、数据丢失。flush()强制把缓冲区数据刷到磁盘close()关闭流关闭前自动执行flush3. 转换流解决编码问题FileReader / FileWriter会直接使用系统默认编码跨平台会乱码。想要手动指定编码使用转换流。InputStreamReader字节输入流 → 字符输入流指定编码读文件OutputStreamWriter字节输出流 → 字符输出流指定编码写文件//示例指定UTF‑8读取文本 try(InputStreamReader isr new InputStreamReader(new FileInputStream(test.txt), StandardCharsets.UTF_8)){ }二、缓冲流提升读写性能原始FileXXX流读写频繁磁盘IO性能差。缓冲流增加内存缓冲区减少磁盘交互大幅提升效率属于包装流必须包裹原始流。字节缓冲流字符缓冲流BufferedInputStreamBufferedReaderBufferedOutputStreamBufferedWriter//字节缓冲流示例 try(BufferedInputStream bis new BufferedInputStream(new FileInputStream(test.jpg))){ }BufferedReader特有方法readLine()直接读取一行字符串非常适合文本处理。BufferedWriter特有方法newLine()写入换行符。缓冲流底层默认缓冲区大小8192字节数据先填满缓冲区再一次性操作磁盘减少IO次数。三、资源关闭两种写法流不关闭会造成文件句柄泄漏程序长时间运行打开大量文件服务直接崩溃。1. 传统 try‑finallyFileInputStream fis null; try { fis new FileInputStream(a.txt); //读写操作 } catch (IOException e) { e.printStackTrace(); } finally { if(fis ! null){ fis.close(); } }缺陷try块和finally块同时抛出异常原始异常会被掩盖丢失。2. Java7 try‑with‑resources【推荐】只要实现AutoCloseable接口在try()括号中定义流对象代码结束自动关闭资源不需要手动finally。try(FileInputStream fis new FileInputStream(a.txt); BufferedInputStream bis new BufferedInputStream(fis)){ //读写 }catch (IOException e){ e.printStackTrace(); }✅代码简洁、自动释放、不会丢失原始异常开发优先使用。❌误区return不会关闭流return只是方法返回不会释放文件句柄。四、字节流 vs 字符流完整对比对比维度字节流字符流顶层抽象InputStream / OutputStreamReader / Writer操作单元byte字节char字符底层原理直接读写二进制字节流编码集转换自带缓冲区无缓冲流额外包装自带缓冲区flush行为不需要flush必须flush/close落盘适用文件图片、视频、压缩包全部文件txt、源码等纯文本乱码风险无编码转换不会乱码编码不匹配直接乱码五、总结read()返回值是int判断结束条件‑1不要强转byte/char再判断。字符流忘记flush/close文件为空数据丢失。FileWriter追加模式构造传入第二个参数true否则每次覆盖旧文件。FileReader/FileWriter跟随系统编码跨平台乱码指定编码优先用转换流。不要拿字符流读取二进制文件文件直接损坏。流资源务必释放优先try‑with‑resources杜绝句柄泄漏。缓冲流是包装流关闭外层缓冲流即可内层被包装流会自动关闭。文件路径Windows路径需要转义D:\\demo.txt也可以写D:/demo.txt。六、补充File类File类不负责文件内容读写只用来表示文件/目录路径完成创建、删除、重命名、判断是否存在、遍历目录等操作。 常用方法exists()判断文件是否存在createNewFile()创建文件mkdir()/mkdirs()创建单级/多级目录delete()删除文件listFiles()遍历目录下全部子文件File不能读写文件内容读写必须依靠IO流。