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

Java I/O 流详解:字符流与字节流的完整指南

一、流(Stream)的基本概念

在Java编程中,流是处理输入输出的核心概念。简单来说,流就像一条"数据管道",数据通过这条管道从源头流向目的地。根据处理数据类型的不同,Java将流分为两大类:

字符流 vs 字节流

字符流:专门用于处理文本数据。这类数据是人类可读的,比如文章、Java源文件、配置文件等。字符流能够正确处理字符编码,确保文本数据的准确读写。
字节流:用于处理二进制数据。这类数据用文本编辑器打开通常无法理解,比如图片文件、MP3音频、视频文件、压缩包等。

二、字符流(Character Streams)

字符流专门为处理文本数据而设计,支持字符编码转换,能够高效地读写文本文件。

2.1 字符输入流(Reader)

字符输入流用于从数据源(如文件、字符串等)读取字符数据。Reader 是所有字符输入流的抽象基类。
主要实现类:
  • FileReader - 用于从文件中读取字符数据
  • InputStreamReader - 将字节流转换为字符流,可以指定字符编码
  • BufferedReader - 提供缓冲功能,提高读取效率,支持按行读取
代码示例:三种字符输入流的使用
import java.io.*;public class CharacterInputExample {public static void main(String[] args) {String filePath = "D:\\IdeaProjects\\JavaTest\\src\\com\\qcby\\a.txt";// 1. 使用 FileReader 读取文件(逐个字符读取)System.out.println("=== FileReader 示例 ===");try (FileReader reader = new FileReader(filePath)) {int data;while ((data = reader.read()) != -1) {System.out.print((char) data);}} catch (IOException e) {e.printStackTrace();}// 2. 使用 InputStreamReader 读取文件(可指定编码)System.out.println("\n=== InputStreamReader 示例 ===");try (InputStreamReader reader = new InputStreamReader(new FileInputStream(filePath), "UTF-8")) {int data;while ((data = reader.read()) != -1) {System.out.print((char) data);}} catch (IOException e) {e.printStackTrace();}// 3. 使用 BufferedReader 按行读取文件(高效方式)System.out.println("\n=== BufferedReader 示例 ===");try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {String line;while ((line = br.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}}
}

2.2 字符输出流(Writer)

字符输出流用于将字符数据写入目标(如文件、控制台等)。Writer 是所有字符输出流的抽象基类。
主要实现类:
  • FileWriter - 用于将字符数据写入文件
  • OutputStreamWriter - 将字符流转换为字节流,可以指定字符编码
  • BufferedWriter - 提供缓冲功能,提高写入效率,支持按行写入
  • PrintWriter - 提供格式化的输出功能
代码示例:三种字符输出流的使用
import java.io.*;public class CharacterOutputExample {public static void main(String[] args) {// 1. 使用 FileWriter 写入文件System.out.println("=== FileWriter 示例 ===");try (FileWriter writer = new FileWriter("output1.txt")) {writer.write("Hello, World!");writer.write("\nThis is a new line.");// 注意:使用try-with-resources不需要手动close} catch (IOException e) {e.printStackTrace();}// 2. 使用 OutputStreamWriter 写入文件System.out.println("=== OutputStreamWriter 示例 ===");try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("output2.txt"), "UTF-8")) {writer.write("Hello, World!");writer.write("\nThis is a new line.");} catch (IOException e) {e.printStackTrace();}// 3. 使用 BufferedWriter 按行写入文件System.out.println("=== BufferedWriter 示例 ===");try (BufferedWriter bw = new BufferedWriter(new FileWriter("output3.txt"))) {bw.write("Hello, World!");bw.newLine(); // 专门的换行方法bw.write("This is a new line.");} catch (IOException e) {e.printStackTrace();}}
}

2.3 Writer的五种写入方法详解

Writer类提供了多种写入方法,满足不同的写入需求:

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;public class WriterMethodsExample {public static void main(String[] args) {try (Writer writer = new FileWriter("output.txt")) {// 1. write(int c) - 写入单个字符writer.write('H'); // 写入字符 'H'// 2. write(char[] cbuf) - 写入整个字符数组char[] array = {'e', 'l', 'l', 'o'};writer.write(array); // 写入 "ello"// 3. write(char[] cbuf, int off, int len) - 写入字符数组的一部分writer.write(array, 1, 2); // 从索引1开始,写入2个字符:"ll"// 4. write(String str) - 写入整个字符串writer.write(", World!"); // 写入 ", World!"// 5. write(String str, int off, int len) - 写入字符串的一部分String str = "\nThis is Java IO.";writer.write(str, 0, 11); // 从索引0开始,写入11个字符:"This is Java"System.out.println("所有数据已成功写入文件!");} catch (IOException e) {e.printStackTrace();}}
}

三、字节流(Byte Streams)

字节流用于处理二进制数据,如图片、音频、视频等文件。字节流直接操作原始字节,不进行字符编码转换。

3.1 字节输入流(InputStream)

InputStream 是所有字节输入流的抽象基类,定义了读取字节数据的基本方法。
核心方法:
  • int read() - 读取单个字节,返回0-255,流末尾返回-1
  • int read(byte[] b) - 读取字节到数组,返回实际读取字节数
  • int read(byte[] b, int off, int len) - 读取指定长度的字节到数组
  • void close() - 关闭流并释放资源
FileInputStream 示例:
import java.io.*;/*** 字节输入流 FileInputStream 使用示例*/
public class FileInputStreamExample {public static void main(String[] args) {FileInputStream fis = null;try {// 1. 创建文件对象File file = new File("D:\\IO\\hello.txt");// 2. 创建输入流对象fis = new FileInputStream(file);// 3. 创建字节数组作为数据容器byte[] buffer = new byte[5];int len; // 记录每次读取的字节个数// 4. 循环读取文件内容while ((len = fis.read(buffer)) != -1) {// 将字节数组转换为字符串输出String str = new String(buffer, 0, len);System.out.print(str);}} catch (IOException e) {e.printStackTrace();} finally {// 5. 释放资源if (fis != null) {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}}
}

3.2 字节输出流(OutputStream)

OutputStream 是所有字节输出流的父类,定义了字节输出的基本操作。
核心方法:
  • void write(byte b) - 写入单个字节
  • void write(byte[] b) - 写入整个字节数组
  • void write(byte[] b, int off, int len) - 写入字节数组的一部分
  • void close() - 关闭输出流
FileOutputStream 示例:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;/*** 字节输出流 FileOutputStream 使用示例*/
public class FileOutputStreamExample {public static void main(String[] args) {FileOutputStream fos = null;try {// 1. 创建文件对象File file = new File("D:\\IO\\hello.txt");// 2. 创建输出流对象fos = new FileOutputStream(file);// 3. 各种写入操作fos.write(97); // 写入字节 97(对应字符 'a')// 写入字符串(需要转换为字节)fos.write("中国人!\r\n".getBytes());// 写入字节数组的一部分fos.write("ABCDEFGH".getBytes(), 2, 4); // 从索引2开始写入4个字节:"CDEF"System.out.println("数据写入完成!");} catch (IOException e) {e.printStackTrace();} finally {// 4. 释放资源if (fos != null) {try {fos.close();} catch (IOException e) {e.printStackTrace();}}}}
}

四、其他重要的流类

4.1 缓冲流(Buffered Streams)

缓冲流通过内置缓冲区显著提高I/O性能:
  • BufferedInputStream - 缓冲字节输入流
  • BufferedOutputStream - 缓冲字节输出流
  • BufferedReader - 缓冲字符输入流
  • BufferedWriter - 缓冲字符输出流

4.2 对象流(Object Streams)

用于对象的序列化和反序列化:
  • ObjectInputStream - 对象输入流
  • ObjectOutputStream - 对象输出流

4.3 转换流(Conversion Streams)

实现字节流与字符流之间的转换:
  • InputStreamReader - 字节流到字符流的桥梁
  • OutputStreamWriter - 字符流到字节流的桥梁

4.4 压缩流(Compression Streams)

处理压缩文件:
  • ZipInputStream - ZIP解压输入流
  • ZipOutputStream - ZIP压缩输出流

4.5 打印流(Print Streams)

提供格式化的输出:
  • PrintWriter - 字符打印流
  • PrintStream - 字节打印流(System.out就是PrintStream)

五、最佳实践和注意事项

5.1 使用try-with-resources

Java 7+推荐使用try-with-resources自动管理资源:
// 推荐方式 - 自动关闭资源
try (FileInputStream fis = new FileInputStream("file.txt");FileOutputStream fos = new FileOutputStream("output.txt")) {// 使用流进行操作
} catch (IOException e) {e.printStackTrace();
}

5.2 选择合适的缓冲区大小

// 根据文件大小选择合适的缓冲区
byte[] buffer = new byte[8192]; // 8KB缓冲区
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {fos.write(buffer, 0, bytesRead);
}

5.3 字符编码的重要性

始终明确指定字符编码:

// 明确指定UTF-8编码
try (InputStreamReader reader = new InputStreamReader(new FileInputStream("file.txt"), StandardCharsets.UTF_8)) {// 读取操作
}

六、总结

Java I/O流提供了强大而灵活的数据处理能力:
  1. 字符流适合处理文本数据,支持字符编码
  2. 字节流适合处理二进制数据,保持数据原始格式
  3. 缓冲流显著提高I/O性能
  4. 正确的资源管理防止内存泄漏
  5. 明确的字符编码避免乱码问题
掌握这些流类的特性和使用场景,能够帮助开发者编写出高效、健壮的Java应用程序。在实际开发中,根据具体需求选择合适的流类,并遵循最佳实践,可以大大提高代码的质量和性能。

http://www.dtcms.com/a/589267.html

相关文章:

  • STM32外设学习-ADC模数转换器(代码部分)四个模块,光敏,热敏,电位,反射式红外。
  • 公众号开发网站购物网站开发介绍
  • 结构型设计模式2
  • 怎么做ppt教程网站灰色项目源码
  • 蛋白质内在无序区域(IDR)预测benchmark
  • 【TIDE DIARY 7】临床指南转公众版系统升级详解
  • STM32百问百答:从硬件到软件全面解析
  • MyBatis-Plus 框架设计模式全景解析
  • 创建型设计模式1
  • AI大数据在医疗健康中的应用与发展趋势
  • 网站规划与开发实训室建设方案个人如何做微商城网站
  • 标准 Python 项目结构
  • 【开发者导航】面向快速模型演示与轻量交互开发的可视化工具:Gradio
  • Vue 项目实战《尚医通》,首页常见科室静态搭建,笔记16
  • 东莞热的建设网站网页视频怎么下载到电脑上
  • 区块链论文速读 CCF A--USENIX Security 2025(4)
  • PHM数据集轴承寿命预测!Transformer-GRU轴承寿命预测MATLAB代码实现
  • 网站错误代码301建设网站如何给页面命名
  • FreeRTOS 学习:(十六)可调用 FromISR 相关 API 函数的中断优先级范围
  • 织梦网站修改使用教程郑州高端网站建设怎么样
  • GPU集群poc测试
  • 操作系统(12)进程描述与控制--进程概述(2)
  • 数据库库、表的创建及处理
  • 空间矢量脉宽调制(Space Vector Pulse Width Modulation)SVPWM基础
  • 链接的迷雾:odr、弱符号与静态库的三国杀
  • Vite + React 项目启动深度踩坑指南
  • 回收网站建设短网址生成器免费
  • Servlet 的 URLPattern配置
  • 传奇购买域名做网站一个网站的渠道网络建设
  • MATLAB中显示X、Y、Z三个方向信号的时频特征,使用时频分析方法