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

JavaOOP学习笔记13:IO流

核心概念:

  1. 流 (Stream):数据在输入源和输出目标之间流动的抽象概念。
    • 输入流 (InputStream / Reader):从源(如文件、网络连接)读取数据到程序。
    • 输出流 (OutputStream / Writer):从程序写出数据到目标(如文件、网络连接)。
  2. 分类维度:
    • 流向:输入流 vs 输出流。
    • 传输单位:字节流 (8-bit) vs 字符流 (16-bit Unicode)。
    • 功能:节点流 (直接操作源/目标) vs 处理流/包装流 (对节点流进行功能增强,如缓冲、转换、对象序列化)。

一、字节流 (Byte Streams) - 处理二进制数据
  • 基类:

    • java.io.InputStream(抽象类)
    • java.io.OutputStream(抽象类)
  • 常用节点流 (直接操作文件、字节数组等):

    • FileInputStream: 从文件读取字节。
    • FileOutputStream: 向文件写入字节。构造函数可指定是否追加 (append=true)。
    try (FileOutputStream fos = new FileOutputStream("data.bin", true)) { // 追加模式 fos.write(65); // 写入 'A' 的 ASCII 码 } // try-with-resources 自动关闭流
    • ByteArrayInputStream: 从内存中的字节数组读取。
    • ByteArrayOutputStream: 向内存中的字节数组写入。
  • 常用处理流 (装饰器模式):

    • BufferedInputStream: 为输入流提供缓冲区,减少磁盘 I/O 次数,提高读取效率。
    • BufferedOutputStream: 为输出流提供缓冲区,减少磁盘 I/O 次数,提高写入效率。
    • DataInputStream: 允许以基本数据类型 (如int,double,boolean) 和String的形式读取字节流。
    • DataOutputStream: 允许以基本数据类型和String的形式写入字节流。
    • ObjectInputStream: 用于反序列化之前由ObjectOutputStream写入的对象。
    • ObjectOutputStream: 用于序列化对象 (实现Serializable接口) 到字节流。
    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.dat")); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.dat"))) { Person p = new Person("张三", 30); oos.writeObject(p); // 序列化 Person readP = (Person) ois.readObject(); // 反序列化 }

二、字符流 (Character Streams) - 处理文本数据 (基于 Unicode)
  • 基类:

    • java.io.Reader(抽象类)
    • java.io.Writer(抽象类)
  • 常用节点流:

    • FileReader: 从文件读取字符。使用平台默认编码或指定编码 (Java 11+FileReader(String, Charset))。可能因编码问题导致乱码。
    • FileWriter: 向文件写入字符。使用平台默认编码或指定编码 (Java 11+)。可能因编码问题导致乱码。
  • 常用处理流:

    • BufferedReader: 为字符输入流提供缓冲区,并提供readLine()方法方便读取整行文本。
    • BufferedWriter: 为字符输出流提供缓冲区,并提供newLine()方法写入平台相关的行分隔符。
    try (BufferedReader br = new BufferedReader(new FileReader("text.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) { String line; while ((line = br.readLine()) != null) { bw.write(line); // 写入一行 bw.newLine(); // 换行 } }
    • InputStreamReader桥梁!将字节输入流 (InputStream) 转换为字符输入流 (Reader),并可指定字符编码(解决乱码关键)。常用构造函数:InputStreamReader(InputStream in, String charsetName)
    • OutputStreamWriter桥梁!将字符输出流 (Writer) 转换为字节输出流 (OutputStream),并可指定字符编码。常用构造函数:OutputStreamWriter(OutputStream out, String charsetName)
    try (BufferedReader br = new BufferedReader( new InputStreamReader( new FileInputStream("gbk.txt"), "GBK")); // 明确指定 GBK 编码读取 BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( new FileOutputStream("utf8.txt"), StandardCharsets.UTF_8))) { // 明确指定 UTF-8 编码写入 // ... 使用 br 读取 GBK 文件,使用 bw 写入 UTF-8 文件 }

三、关键点与最佳实践
  1. 字符编码 (Charset):处理文本时,务必明确指定字符编码(如UTF-8,GBK),尤其是在涉及不同系统或网络传输时。使用InputStreamReaderOutputStreamWriter是控制编码的最佳方式。避免直接使用FileReader/FileWriter的默认编码。
  2. 缓冲 (Buffering):对于文件或网络 I/O,总是使用缓冲流 (BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter) 来包装节点流,可以显著提高性能。
  3. 资源管理:使用try-with-resources语句 (Java 7+) 确保流在操作完成后自动关闭,避免资源泄漏。流需要关闭。
    try (InputStream in = ...; OutputStream out = ...) { // 使用流 } // 自动关闭 in 和 out
  4. 装饰器模式 (Decorator Pattern):Java IO 流的设计大量使用了装饰器模式。处理流 (BufferedXxx,DataXxx等) 可以层层嵌套包装节点流,动态地添加功能 (缓冲、数据类型转换、对象序列化等)。
  5. 文件复制示例 (字节流 + 缓冲):
    try (InputStream in = new BufferedInputStream(new FileInputStream("source.jpg")); OutputStream out = new BufferedOutputStream(new FileOutputStream("copy.jpg"))) { byte[] buffer = new byte[8192]; // 8KB 缓冲区 int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } }
  6. 序列化 (Serialization):
    • 需要序列化的类必须实现java.io.Serializable接口 (标记接口)。
    • 使用ObjectOutputStreamObjectInputStream进行序列化和反序列化。
    • 注意transient关键字修饰的字段不会被序列化。
    • 注意版本兼容性问题 (serialVersionUID)。

四、总结

Java IO 提供了丰富的流类来处理各种输入输出需求。理解字节流与字符流的区别、节点流与处理流的关系、字符编码的重要性以及资源管理的最佳实践 (try-with-resources) 是掌握 Java IO 的关键。在实际开发中,结合缓冲流和明确指定编码是提高性能和避免乱码的标准做法。

http://www.jsqmd.com/news/475704/

相关文章:

  • 跨平台文件系统的Windows工具:WinBtrfs打破系统边界的存储解决方案
  • 第三十五天--小人物的坚持--网络编程
  • 如何用AI破解图像分层难题?LayerDivider实战指南
  • (397页PPT)麦肯锡高级咨询培训手册(附下载方式)
  • 智能小车最短路径规划算法研究:基于RRT与Dubins的混合A*方法与Dubins相结合方法的探讨
  • 351. Java IO API - Java 文件操作:java.io.File 与 java.nio.file 功能对比 - 3
  • Python基于flask-django校园个人闲置物品换购平台的设计与开发
  • Qwen-Max 8G 内存本地部署方案(轻量化可用版)
  • 如何实现精准号码定位?开源工具让位置查询变简单
  • 5分钟上手!数据可视化开源工具NPYViewer如何解决科研与工程中的3大核心痛点
  • 3分钟实现本地图片秒搜:ImageSearch从入门到精通
  • 3步释放显卡潜能:DLSS Swapper让游戏帧率提升30%的开源工具
  • 3.13 121~127(无123,124)翻译 单词
  • 数据库实体关系设计、SQL 连接查询及MyBatis 多表映射
  • 如何用wow_api提升魔兽世界宏命令效率?5个进阶技巧全解析
  • 2026电力交易:光伏+25%背后的隐忧,你的交易策略急需一张“气象底图”
  • 怎么给OpenClaw安装更多实用的‘skills‘?
  • 突破硬件限制:让旧Mac焕发新生的6大核心策略
  • Windows驱动存储终极解决方案:DriverStore Explorer效率革命
  • 猫抓cat-catch终极全攻略:零基础掌握网页资源高效捕获技术
  • 3大维度解析开源GPS追踪系统:从技术突破到商业落地
  • 3大技术突破让老游戏在Windows 11重获新生:DDrawCompat全解析
  • 5个核心功能解决内容创作者视频管理痛点
  • FanControl风扇控制进阶指南:从问题诊断到智能调节
  • SCI论文降AI实战:从80%+到安全线,这份指南帮你搞定国际期刊
  • 2023老旧Mac设备系统升级实战指南:从硬件限制到性能重生
  • 基于微信小程序的用户口味偏好点餐盲盒系统[小程序]-计算机毕业设计源码+LW文档
  • 老旧设备优化指南:使用OpenCore Legacy Patcher开源工具实现macOS系统升级
  • AirPodsDesktop深度测评:重构Windows平台耳机体验的突破局限之作
  • Windows Hadoop配置技术解析:winutils.exe的跨平台适配实践