当前位置: 首页 > backend >正文

Java IO 流-详解

介 绍

Java 的 IO(输入 / 输出)流是处理设备间数据传输的核心机制,主要用于读取和写入数据。

IO 流根据不同的分类方式可以分为多种类型:

  1. 按流向划分输入流(InputStream/Reader)和输出流(OutputStream/Writer)
  2. 按数据类型划分字节流(InputStream/OutputStream)和字符流(Reader/Writer)
  3. 按功能划分节点流(直接操作数据源)和处理流(对节点流进行包装)

核心用法、区别及适用场景

一、字节流(InputStream/OutputStream)

特点:以字节为单位处理数据,可操作所有类型文件(文本、图片、音频等)。

1. 节点字节流
  • FileInputStream/FileOutputStream(文件字节流)
    // 读取文件
    try (FileInputStream fis = new FileInputStream("input.txt")) {byte[] buffer = new byte[1024];int len;while ((len = fis.read(buffer)) != -1) {// 处理读取的字节数据}
    }// 写入文件
    try (FileOutputStream fos = new FileOutputStream("output.txt")) {byte[] data = "Hello".getBytes();fos.write(data); // 写入字节数组
    }
    
    适用场景:读写二进制文件(图片、视频)或简单文本文件。
2. 处理字节流
  • BufferedInputStream/BufferedOutputStream(缓冲字节流)

    // 带缓冲区的文件读写(性能更优)
    try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.jpg"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.jpg"))) {byte[] buffer = new byte[8192];int len;while ((len = bis.read(buffer)) != -1) {bos.write(buffer, 0, len); // 批量写入,减少IO次数}
    }
    
    核心优势:内部维护缓冲区,减少磁盘 IO 次数,大幅提升大文件处理效率。
  • DataInputStream/DataOutputStream(数据字节流)

    // 读写基本数据类型(保留数据类型信息)
    try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.dat"))) {dos.writeInt(100);    // 写入intdos.writeDouble(3.14); // 写入doubledos.writeUTF("字符串"); // 写入UTF字符串
    }try (DataInputStream dis = new DataInputStream(new FileInputStream("data.dat"))) {int num = dis.readInt();double d = dis.readDouble();
    }
    
    适用场景:需要按数据类型读写时(如保存配置文件、网络传输基本类型)。
  • ObjectInputStream/ObjectOutputStream(对象流)

    // 序列化对象(需实现Serializable接口)
    class User implements Serializable {private static final long serialVersionUID = 1L; // 版本控制private String name;// get/set...
    }// 序列化
    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.obj"))) {oos.writeObject(new User("张三"));
    }// 反序列化
    try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.obj"))) {User user = (User) ois.readObject();
    }
    

    核心特点:实现对象的持久化存储或网络传输,transient修饰的字段不参与序列化。

二、字符流(Reader/Writer)

特点:以字符为单位处理数据,自动处理编码转换,仅适用于文本文件。

1. 节点字符流
  • FileReader/FileWriter(文件字符流)
    // 读取文本(默认编码)
    try (FileReader fr = new FileReader("text.txt")) {char[] buffer = new char[1024];int len;while ((len = fr.read(buffer)) != -1) {System.out.print(new String(buffer, 0, len));}
    }// 写入文本
    try (FileWriter fw = new FileWriter("output.txt")) {fw.write("中文文本"); // 直接写入字符
    }
    
    局限性:依赖系统默认编码,可能导致跨平台乱码。
2. 处理字符流
  • InputStreamReader/OutputStreamWriter(转换流)

    // 指定编码读写(解决乱码问题)
    try (InputStreamReader isr = new InputStreamReader(new FileInputStream("text.txt"), StandardCharsets.UTF_8);OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("output.txt"), StandardCharsets.UTF_8)) {char[] buffer = new char[1024];int len;while ((len = isr.read(buffer)) != -1) {osw.write(buffer, 0, len);}
    }
    
    核心作用:字节流与字符流的桥梁,可指定编码(如 UTF-8),彻底解决乱码问题。
  • BufferedReader/BufferedWriter(缓冲字符流)

    // 高效读写文本,支持按行操作
    try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("text.txt"), "UTF-8"));BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("out.txt"), "UTF-8"))) {String line;while ((line = br.readLine()) != null) { // 按行读取bw.write(line);bw.newLine(); // 跨平台换行}
    }
    
    核心优势:提供readLine()newLine()方法,适合处理换行符敏感的文本(如 CSV、配置文件)。
  • PrintWriter(打印流)

    // 方便的文本输出(支持自动刷新)
    try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("log.txt"), "UTF-8"), true)) {pw.println("日志信息1"); // 自动换行pw.printf("用户%s登录成功", "张三"); // 格式化输出
    }
    
    适用场景:日志输出、格式化文本写入(如报表生成)。
三、特殊流
  1. ByteArrayInputStream/ByteArrayOutputStream(字节数组流)

    // 内存中处理数据(无磁盘IO)
    byte[] data = "内存数据".getBytes();
    try (ByteArrayInputStream bais = new ByteArrayInputStream(data);ByteArrayOutputStream baos = new ByteArrayOutputStream()) {byte[] buffer = new byte[1024];int len;while ((len = bais.read(buffer)) != -1) {baos.write(buffer, 0, len); // 数据在内存中流转}System.out.println(baos.toString());
    }
    
    适用场景临时数据处理(如数据加密、压缩前的内存缓存)。
  2. PipedInputStream/PipedOutputStream(管道流)

    // 线程间通信
    PipedInputStream pis = new PipedInputStream();
    PipedOutputStream pos = new PipedOutputStream(pis); // 绑定输入输出流// 线程1:写入数据
    new Thread(() -> {try { pos.write("线程间通信".getBytes()); } catch (IOException e) { e.printStackTrace(); }
    }).start();// 线程2:读取数据
    new Thread(() -> {try { byte[] buf = new byte[1024];pis.read(buf); } catch (IOException e) { e.printStackTrace(); }
    }).start();
    
    适用场景同一进程内的线程间数据传递。
四、核心区别与选择指南
维度字节流字符流
处理单位字节(8 位)字符(根据编码,如 UTF-8 为 1-4 字节)
处理对象所有文件(文本 + 二进制)仅文本文件
编码依赖不依赖编码依赖编码(需注意乱码)
核心类InputStream/OutputStreamReader/Writer

选择原则

  • 二进制文件(图片、视频)→ 字节流 + 缓冲流
  • 文本文件 → 字符流(优先用转换流指定编码)+ 缓冲流
  • 基本数据类型 → Data 流
  • 对象持久化 → 对象流
  • 内存数据处理 → 字节数组流
  • 线程通信 → 管道流
五、最佳实践
  1. 资源自动关闭始终使用try-with-resources语法(JDK7+),无需手动调用close()
  2. 缓冲流优先处理大文件时,用缓冲流包装节点流提升性能。
  3. 编码显式化文本处理时通过InputStreamReader/OutputStreamWriter指定编码(如 UTF-8)。
  4. 序列化版本控制实现Serializable的类必须定义serialVersionUID,避免版本冲突。
http://www.xdnf.cn/news/18991.html

相关文章:

  • 从零开始学习单片机16
  • 循环高级(2)
  • 血缘元数据采集开放标准:OpenLineage Integrations Manually Annotated Lineage
  • 企业级数据库管理实战(二):数据库权限最小化原则的落地方法
  • 【分治法 BFS 质因数分解】P12255 [蓝桥杯 2024 国 Java B] 园丁|普及+
  • 智慧养老建设方案(PPT)
  • 开源大语言模型(Qwen3)
  • 深入探讨可视化技术如何实现安全监测
  • 【小白笔记】Visual Studio 在 2025年7月更新的功能说明(英文单词记忆)
  • 智慧工地系统:基于Java微服务与信创国产化的建筑施工数字化管理平台
  • 171-178CSS3新增
  • NullPointerException 空指针异常,为什么老是遇到?
  • 评价指标FID/R Precision
  • vscode编辑器中设置断点,不会自动启动调试器
  • 介绍⼀下Llama的结构
  • Spring Boot 整合 MongoDB:CRUD 与聚合查询实战
  • Jenkins 全方位指南:安装、配置、部署与实战应用(含图解)
  • 如何规划一年、三年、五年的IP发展路线图?
  • 01.<<基础入门:了解网络的基本概念>>
  • Leetcode 深度优先搜索 (15)
  • WINTRUST!_ExplodeMessag函数中的pCatAdd
  • Yolov8 pose 推理部署笔记
  • Vue开发避坑:箭头函数与普通函数的正确使用指南
  • LeetCode 刷题【55. 跳跃游戏】
  • 从协作机器人到智能协作机器人:工业革命的下一跳
  • 【JavaScript】递归的问题以及优化方法
  • 安宝特方案丨安宝特工业AR全链路解决方案
  • Unity游戏打包——iOS打包基础、上传
  • java后端的各种注解
  • Linux 禁止 su 的几种限制手段:从 NoNewPrivileges 到 PAM 配置