Java IO输入输出流精讲|流的作用、划分方式与使用场景梳理
前言在Java程序运行过程中经常需要和外部设备交换数据读取本地文件内容、向控制台打印信息、网络收发数据、读写内存缓存等。如果没有统一的数据传输模型每种设备都要单独编写一套读写逻辑代码会极度冗余且难以维护。Java IO输入输出流应运而生它把所有数据传输行为抽象成流统一一套API完成所有IO操作。接下来本文分为两大块第一部分讲解流的核心作用第二部分多角度划分所有IO流最后附上实操代码示例。一、IO流的核心作用1. 统一封装数据传输逻辑无论是文件、键盘、显示器、网络Socket、内存数组全部统一抽象为“流”对象。开发者不需要区分底层设备差异调用read()、write()通用方法即可完成读写降低学习与开发成本。2. 实现数据持久化与临时交互输出流将程序内存中的数据写出到外部文件、控制台实现数据持久保存输入流把外部设备的数据读取到程序内存中供程序运算、解析使用。3. 支持分段缓冲读写提升性能流底层自带缓冲机制不会每次读写都直接操作磁盘/网络批量传输减少IO交互次数大幅提升文件读写、数据传输效率。4. 适配多场景数据处理覆盖日常开发绝大多数场景控制台输入输出Scanner、System.in、System.out本地文件读写文档、图片、视频、配置文件网络通信数据传输Socket流内存数组、字符串临时读写对象序列化与反序列化对象流二、IO流的多种划分方式2.1 按数据传输方向划分最基础分类核心区分程序内存 ↔ 外部资源输入流读数据流向外部设备 → 程序内存作用读取外部数据到程序中顶层父类字节输入流InputStream字符输入流Reader典型实现FileInputStream、FileReader、BufferedReader输出流写数据流向程序内存 → 外部设备作用把程序数据写出保存顶层父类字节输出流OutputStream字符输出流Writer典型实现FileOutputStream、FileWriter、PrintWriter2.2 按数据传输单位划分字节流 / 字符流1. 字节流传输单位1字节8bit处理所有二进制数据顶层父类InputStream / OutputStream适用场景图片、视频、音频、压缩包、exe程序等所有非文本文件特点不处理编码直接原始二进制传输无字符转换2. 字符流传输单位1字符根据编码1~3字节专门处理文本顶层父类Reader / Writer适用场景txt、java、html、配置文件等纯文本特点内置编码转换自动处理中文乱码问题仅能操作文本2.3 按功能层级划分节点流 vs 处理流1. 节点流底层流直接对接数据源/目标是真正操作文件、设备的基础流示例文件节点流FileInputStream、FileReader、FileOutputStream、FileWriter数组节点流ByteArrayInputStream、CharArrayReader2. 处理流包装流/缓冲流不直接对接数据源包裹节点流增强原有流功能常见类型缓冲流BufferedInputStream、BufferedReader增加缓冲区提升速度转换流InputStreamReader、OutputStreamWriter字节流转字符流指定编码打印流PrintStream、PrintWriter提供便捷print/println方法对象流ObjectInputStream、ObjectOutputStream实现对象序列化2.4 特殊分类标准IO流控制台流Java预设三个全局标准流无需手动创建System.in标准输入流键盘输入字节流System.out标准输出流控制台打印打印流System.err标准错误输出流错误信息打印三、各类流适用场景总结读写图片、视频 → 字节流 FileInputStream / FileOutputStream读写txt、代码、配置文件 → 字符流 FileReader / FileWriter 缓冲流字节流读取文本需指定编码 → 转换流 InputStreamReader快速打印数据、自动换行 → PrintWriter读写对象、集合持久化 → Object流大批量文件读写提速 → Buffered缓冲流四、实操代码示例示例1字节流复制图片二进制文件import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;/*** 字节流复制图片/视频等二进制文件*/public class ByteStreamCopyDemo {public static void main(String[] args) {// 源文件路径、目标文件路径String srcPath D:/test.jpg;String destPath D:/test_copy.jpg;FileInputStream fis null;FileOutputStream fos null;try {fis new FileInputStream(srcPath);fos new FileOutputStream(destPath);// 缓冲数组一次读写1024字节byte[] buffer new byte[1024];int len;// 循环读取len为实际读到的字节数while ((len fis.read(buffer)) ! -1) {fos.write(buffer, 0, len);}System.out.println(图片复制完成);} catch (IOException e) {e.printStackTrace();} finally {// 关闭流释放资源try {if (fos ! null) fos.close();if (fis ! null) fis.close();} catch (IOException e) {e.printStackTrace();}}}}示例2字符缓冲流读写文本文件处理中文import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;/*** 字符缓冲流读写txt文本支持按行读取*/public class CharBufferReadWriteDemo {public static void main(String[] args) {String filePath D:/demo.txt;// 写入文本try (BufferedWriter bw new BufferedWriter(new FileWriter(filePath))) {bw.write(Java IO流学习笔记);bw.newLine(); // 换行bw.write(字节流处理二进制字符流处理文本);bw.flush(); // 刷新缓冲区} catch (IOException e) {e.printStackTrace();}// 读取文本try (BufferedReader br new BufferedReader(new FileReader(filePath))) {String line;// 逐行读取while ((line br.readLine()) ! null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}}}示例3转换流字节流转字符流指定编码防乱码import java.io.FileInputStream;import java.io.InputStreamReader;import java.io.BufferedReader;import java.io.IOException;/*** 转换流字节流转字符流手动指定UTF-8编码*/public class ConvertStreamDemo {public static void main(String[] args) {try (// 字节节点流FileInputStream fis new FileInputStream(D:/utf8.txt);// 转换流指定编码InputStreamReader isr new InputStreamReader(fis, UTF-8);// 包装缓冲流提升效率BufferedReader br new BufferedReader(isr)) {String content;while ((content br.readLine()) ! null) {System.out.println(content);}} catch (IOException e) {e.printStackTrace();}}}示例4标准流控制台输入输出import java.util.Scanner;/*** 标准IO流控制台键盘输入、控制台输出*/public class StandardIODemo {public static void main(String[] args) {// System.in 标准输入流Scanner封装简化读取Scanner sc new Scanner(System.in);System.out.print(请输入姓名);String name sc.next();// System.out 标准输出流System.out.println(你输入的姓名 name);sc.close();}}五、总结流的核心作用统一抽象所有IO数据传输简化不同设备读写操作兼顾性能与易用性三大核心划分维度流向输入/输出、传输单位字节/字符、层级节点/处理开发选择流的核心原则文本优先字符流二进制文件必须字节流大批量读写搭配缓冲流提升效率编码乱码解决方案使用转换流手动指定文件编码避免平台默认编码差异问题。文末拓展思考字节流和字符流能否互相转换转换流的底层原理是什么使用缓冲流后为什么必须调用flush()或close()才能保证数据写入对象流序列化时transient关键字会产生什么效果补充小贴士JDK7支持try-with-resources语法流会自动关闭省去finally手动释放代码所有IO操作都受检IOException必须捕获或抛出字符流仅适用于文本图片、视频等二进制文件强行用字符流会损坏文件。