Java IO流入门:字节流与字符流区别及核心操作示例

慢慢来
慢慢来
发布时间:2026-10-14| 4人浏览过
原创

Java I/O(Input/Output)是进行设备间数据传输的核心机制。根据数据类型和处理效率的不同,Java提供了字节流(如InputStream、OutputStream)和字符流(如Reader、Writer)两大类。本文将详细解析两者的区别,并通过具体的代码示例,演示如何使用这些流对象完成文件的创建、内容读取、文件复制以及利用缓冲区和工具类提高I/O操作效率。

字节流与字符流的基础概念

Java所有的I/O操作均封装在java.io包中。理解I/O的关键在于掌握分类逻辑:

  • 按流向划分:输入流(用于读取数据,基类为InputStream和Reader)与输出流(用于写入数据,基类为OutputStream和Writer)。
  • 按操作数据单位划分:
    • 字节流:以字节(8 bit)为单位进行操作,适用于处理二进制文件(如图片、音频)或任何数据类型的通用传输。
    • 字符流:以字符(通常是16 bit Unicode)为单位进行操作,专门用于处理纯文本数据。字符流内部通常包含编码转换逻辑,能更好地兼容不同平台的文字标准。

Java继承体系遵循严格的命名规范:子类名称通常由父类名作为后缀。例如,操作文件的字节输入流为FileInputStream,字符输入流为FileReader。

字符流的基本操作

在处理纯文本时,推荐使用字符流。以下示例展示了如何使用FileWriter和FileReader进行基础的文本写入与读取。

第一步:使用 FileWriter 写入文本

目的:将指定字符串内容写入到目标文件中。若文件不存在则自动创建;若已存在且未设置追加模式,原有内容将被覆盖。注意,写入后必须调用flush()刷新缓冲区,或在关闭流时自动刷出。

package javase.day18;

import java.io.FileWriter;
import java.io.IOException;

public class FileWriterDemo {
    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            // 创建 FileWriter 对象,指定路径 "C:\\java_test\\FileWriterTest.txt"
            // 若目录不存在需提前创建,否则可能抛出异常
            fw = new FileWriter("C:\\java_test\\FileWriterTest.txt");
            
            // 将字符串写入流缓冲区
            fw.write("alex test23");
            
            // 强制将缓冲区数据写入磁盘文件
            fw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源,关闭前会自动执行一次 flush
            try {
                if (fw != null) {
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

第二步:使用 FileReader 读取文本

目的:从文件中读取字符数据并打印到控制台。通常建议使用字符数组作为缓冲区以提高读取效率,避免频繁的系统调用。

package javase.day18;

import java.io.FileReader;
import java.io.IOException;

public class FileReaderTest {
    public static void main(String[] args) {
        try {
            // 读取源文件 "C:\\java_test\\SystemDemo.java"
            FileReader fr = new FileReader("C:\\java_test\\SystemDemo.java");
            char[] buf = new char[1024]; // 定义缓冲区
            int num = 0;
            
            // 循环读取,返回 -1 表示读完
            while ((num = fr.read(buf)) != -1) {
                // 将读取到的有效字符转换为字符串输出
                System.out.println(new String(buf, 0, num));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

文件复制的两种策略

文件复制本质上是“读取源文件”+“写入目标文件”。根据读取粒度的不同,可分为逐字符处理和块处理。块处理(使用数组缓冲)性能通常远优于逐字符处理。

第一种方式:逐字符复制(效率较低)

每次读取一个整数(对应一个char),立即写入。虽然代码简单,但频繁的方法调用会导致较大的性能开销。

第二种方式:数组缓冲复制(推荐)

一次性读取固定大小的字符数组,然后写入对应数量的字符。这种方式大幅减少了系统交互次数。

package javase.day18;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyText {
    public static void main(String[] args) {
        try {
            copy_2(); // 建议使用缓冲方式
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 方式1:逐个字符读写
    public static void copy_1() throws IOException {
        FileWriter fw = new FileWriter("C:\\java_test\\Copy_SystemDemo.java");
        FileReader fr = new FileReader("C:\\java_test\\SystemDemo.java");
        int num = 0;
        // 每次只读一个字符
        while ((num = fr.read()) != -1) {
            fw.write(num);
        }
        fw.close();
        fr.close();
    }

    // 方式2:缓存数组读写
    public static void copy_2() throws IOException {
        FileWriter fw = new FileWriter("C:\\java_test\\Copy_SystemDemo.java");
        FileReader fr = new FileReader("C:\\java_test\\SystemDemo.java");
        char[] buf = new char[1024];
        int num = 0;
        // 批量读取并存入buf
        while ((num = fr.read(buf)) != -1) {
            // 只写入实际读取到的有效部分
            fw.write(buf, 0, num);
        }
        fw.close();
        fr.close();
    }
}

使用 BufferedReader/BufferedWriter 提高效率

为了进一步提升文本处理的便利性,Java提供了缓冲字符流:BufferedReader 和 BufferedWriter。它们包裹在底层节点流之外,不仅能提高读写速度,还提供了更便捷的方法,如readLine()可以直接读取一整行文本,无需手动处理换行符。

IO 操作通用选择规律

面对复杂的I/O需求,可遵循以下步骤确定具体的类:

  1. 明确源和目的:
    • 源:输入流 (InputStream, Reader)
    • 目的:输出流 (OutputStream, Writer)
  2. 判断数据性质:
    • 是否为纯文本?是 → 选择字符流(Reader/Writer系列);否 → 选择字节流(InputStream/OutputStream系列)。
  3. 确定具体设备:
    • 源设备:硬盘(File...)、内存(字节数组)、键盘(System.in)。
    • 目的设备:硬盘(File...)、控制台(System.out)。
  4. 优化需求:
    • 是否需要高速读写?若是,在外层包裹Buffered...类。

实用的 IO 工具类实现

在实际开发中,经常需要将整个文件内容读取为字符串,或者将文本写入文件。以下是一个简单的工具类IOUtil,整合了常用的文件读写功能。

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;

public class IOUtil {

    /**
     * 将文件读入到一个String
     * 利用 FileReader + BufferedReader(readLine)
     */
    public static String fileReaderStringHandle(String fileName) {
        StringBuilder sb = new StringBuilder();
        try (
            // 使用 try-with-resources 自动管理资源
            BufferedReader in = new BufferedReader(new FileReader(new File(fileName).getAbsoluteFile()))
        ) {
            String line;
            while ((line = in.readLine()) != null) {
                sb.append(line);
                sb.append("\n");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return sb.toString();
    }

    /**
     * 将文件读入到一个 byte[]
     * 利用 FileInputStream + BufferedInputStream
     */
    public static byte[] fileReaderByteHandle(String fileName) {
        try (
            BufferedInputStream bf = new BufferedInputStream(new FileInputStream(fileName))
        ) {
            byte[] data = new byte[bf.available()];
            bf.read(data);
            return data;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将指定的 text 写入到文件中
     * 使用 PrintWriter 方便格式化输出
     */
    public static void fileWriterHandle(String fileName, String text) {
        try (
            PrintWriter out = new PrintWriter(new File(fileName).getAbsoluteFile())
        ) {
            out.print(text);
        } catch (Exception e) { // PrintWriter 构造器不抛 IOException,但其他方法可能抛
             // 实际生产中建议更细致的异常处理
             throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws IOException {
        // 测试字符串读取
        System.out.print(fileReaderStringHandle("src/IOUtil.java"));

        // 测试字节读取
        for (byte b : fileReaderByteHandle("src/IOUtil.java")) {
            System.out.print(b);
        }

        // 测试文件写入
        fileWriterHandle("zj.txt", fileReaderStringHandle("src/IOUtil.java"));
    }
}

以上就是Java IO流中字节流与字符流操作的详细内容,更多关于Java文件读写与流处理的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。