一文吃透Java IO流!从底层原理到实战代码(新手必看)

一文吃透Java IO流!从底层原理到实战代码(新手必看)

前言

但凡学 Java,IO 流是绕不开的核心基础!

无论是日常开发中的文件读写、日志记录、图片上传下载,还是网络通信、数据持久化,底层全部依赖 IO 流实现。同时它也是Java 面试高频考点、期末必考知识点。

很多初学者学 IO 流都会陷入误区:类太多、名字太像、不知道该用哪一个、代码写完总是乱码 / 报错。

今天这篇博客,我用最通俗的语言 + 分类梳理 + 可直接运行的实战代码,带你从零吃透 Java IO 基础流,看完直接告别 IO 流混乱!

一、什么是 IO 流?核心本质

1. IO 含义

- I(Input 输入):读取数据,数据从「外部设备」流向「Java 程序」

例:读取电脑本地文件内容到程序中

- O(Output 输出):写入数据,数据从「Java 程序」流向「外部设备」

例:把程序中的文字、数据保存到本地文件

2. 流的本质

流就是数据传输的通道,像水管一样,数据以字节 / 字符的形式,有序、单向、逐次传输。

IO 流的核心特点:单向传输、顺序读写、用完必关闭。

二、IO 流核心分类(重中之重)

Java IO 流体系庞大,但所有流的顶层父类只有四个,记住这四个类,就掌握了 80% 的 IO 基础!

1. 按数据类型分类(最核心区分)

(1)字节流(Byte)

- 操作单位:1 个字节(8 位)

- 支持文件:所有文件(文本、图片、视频、音频、压缩包等)

- 适用场景:文件复制、传输所有类型文件

- 顶层父类:

- 输入:InputStream(抽象类)

- 输出:OutputStream(抽象类)

(2)字符流(Char)

- 操作单位:1 个字符(中文 2 字节、英文 1 字节,自动适配编码)

- 支持文件:仅纯文本文件(txt、java、md 等)

- 适用场景:读写文本内容,彻底解决中文乱码

- 顶层父类:

- 输入:Reader(抽象类)

- 输出:Writer(抽象类)

2. 按传输方向分类

- 输入流:读数据(外部 → 程序)

- 输出流:写数据(程序 → 外部)

3. 极简选择口诀(新手直接背)

1. 图片 / 视频 / 文件复制 → 无脑用字节流

2. 读写纯文本、处理中文 → 无脑用字符流

三、四大基础流实战(最常用)

所有 IO 资源属于系统资源,Java 垃圾回收无法自动释放,必须手动关闭!

推荐使用 try-with-resources 语法,自动关闭流,简洁且安全。

1. 字节输入流 FileInputStream(读文件)

作用:读取任意类型文件的字节数据

import java.io.FileInputStream;

import java.io.IOException;

/**

* 字节输入流:读取文件(支持所有文件类型)

*/

public class FileInputStreamDemo {

public static void main(String[] args) {

// try-with-resources:自动关闭流

try (FileInputStream fis = new FileInputStream("test.txt")) {

// 定义字节数组缓冲区,一次读取1024字节,效率更高

byte[] buf = new byte[1024];

int len; // 记录本次读取的字节数

// 循环读取,len=-1 表示读取完毕

while ((len = fis.read(buf)) != -1) {

// 字节数组转字符串,输出读取内容

String content = new String(buf, 0, len);

System.out.print(content);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

2. 字节输出流 FileOutputStream(写文件)

作用:向文件写入字节数据,支持覆盖 / 追加写入

import java.io.FileOutputStream;

import java.io.IOException;

/**

* 字节输出流:写入文件

* 第二个参数true:追加写入;默认false:覆盖写入

*/

public class FileOutputStreamDemo {

public static void main(String[] args) {

try (FileOutputStream fos = new FileOutputStream("test.txt", true)) {

// 写入字符串,转字节数组

String str = "\nJava IO流实战测试";

fos.write(str.getBytes());

System.out.println("数据写入成功!");

} catch (IOException e) {

e.printStackTrace();

}

}

}

3. 字符输入流 FileReader(读文本)

专门优化文本读取,自动处理字符编码,中文无乱码

import java.io.FileReader;

import java.io.IOException;

/**

* 字符输入流:只读纯文本文件

*/

public class FileReaderDemo {

public static void main(String[] args) {

try (FileReader fr = new FileReader("test.txt")) {

// 字符缓冲区

char[] chars = new char[1024];

int len;

while ((len = fr.read(chars)) != -1) {

System.out.print(new String(chars, 0, len));

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

4. 字符输出流 FileWriter(写文本)

专门用于文本写入,操作更简洁

import java.io.FileWriter;

import java.io.IOException;

/**

* 字符输出流:只写纯文本文件

*/

public class FileWriterDemo {

public static void main(String[] args) {

try (FileWriter fw = new FileWriter("test.txt", true)) {

// 直接写入字符串,无需转字节

fw.write("\n字符流写入中文测试,无乱码!");

// 刷新缓冲区(字符流必须刷新,否则数据滞留缓冲区)

fw.flush();

System.out.println("文本写入成功!");

} catch (IOException e) {

e.printStackTrace();

}

}

}

四、高效缓冲流(开发首选!)

基础流是单字节 / 单字符读写,频繁 IO 操作效率极低!

缓冲流自带内置缓冲区,批量读写数据,效率提升数十倍,实际开发一律用缓冲流。

缓冲流对应四类:

1. 字节缓冲:BufferedInputStream / BufferedOutputStream

2. 字符缓冲:BufferedReader / BufferedWriter

核心优势

- 减少磁盘 IO 次数,性能极高

- 字符缓冲流独有:readLine () 逐行读取、newLine() 换行,极度方便

实战:字符缓冲流读写文本(最常用)

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

/**

* 缓冲流实战:高效读写文本

*/

public class BufferedIODemo {

public static void main(String[] args) {

// 写入数据

try (BufferedWriter bw = new BufferedWriter(new FileWriter("bufferTest.txt"))) {

bw.write("Java IO缓冲流测试");

bw.newLine(); // 自动换行(跨平台兼容)

bw.write("高效读写,开发首选");

bw.flush();

} catch (IOException e) {

e.printStackTrace();

}

// 读取数据(逐行读取)

try (BufferedReader br = new BufferedReader(new FileReader("bufferTest.txt"))) {

String line;

// 逐行读取,null表示读取完毕

while ((line = br.readLine()) != null) {

System.out.println(line);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

五、转换流(解决乱码终极方案)

痛点

FileReader/FileWriter 默认跟随系统编码,Windows 默认 GBK,IDEA 默认 UTF-8,极易出现中文乱码!

核心作用

字节流 → 字符流,并手动指定编码格式(UTF-8/GBK),彻底解决乱码问题

两个核心类:

1. InputStreamReader:字节输入流转字符输入流(指定编码读)

2. OutputStreamWriter:字节输出流转字符输出流(指定编码写)

编码统一实战

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.io.IOException;

/**

* 转换流:指定UTF-8编码,彻底解决乱码

*/

public class ConvertIODemo {

public static void main(String[] args) {

// 以UTF-8编码读取文件

try (BufferedReader br = new BufferedReader(

new InputStreamReader(new FileInputStream("test.txt"), "UTF-8"))) {

// 以UTF-8编码写入文件

try (BufferedWriter bw = new BufferedWriter(

new OutputStreamWriter(new FileOutputStream("utf8_test.txt"), "UTF-8"))) {

String line;

while ((line = br.readLine()) != null) {

bw.write(line);

bw.newLine();

}

System.out.println("编码统一复制完成,无乱码!");

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

六、IO 流高频必备:文件复制通用工具

结合字节缓冲流,实现任意文件无损复制(图片、视频、文本通用),开发高频工具方法:

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

/**

* 通用文件复制工具类(支持所有文件类型)

*/

public class FileCopyUtil {

public static void main(String[] args) {

// 源文件路径、目标文件路径

copyFile("source.jpg", "target.jpg");

System.out.println("文件复制成功!");

}

/**

* 文件复制通用方法

* @param srcPath 源文件路径

* @param destPath 目标文件路径

*/

public static void copyFile(String srcPath, String destPath) {

try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcPath));

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destPath))) {

byte[] buf = new byte[1024 * 8]; // 8KB缓冲区

int len;

while ((len = bis.read(buf)) != -1) {

bos.write(buf, 0, len);

}

bos.flush(); // 刷新缓冲区

} catch (IOException e) {

e.printStackTrace();

}

}

}

七、新手常见坑 & 避坑总结

1. 流必须关闭 / 刷新

- 字符流不 flush ()、不 close () → 数据滞留缓冲区,写入失效

- 不关闭流 → 造成资源泄露,占用系统资源

2. 乱码问题解决方案

- 不要用默认字符流!读写不同编码文件,一律用转换流指定 UTF-8

3. 流选择禁忌

- 图片、视频禁止使用字符流,会导致文件损坏、无法打开

4. 性能禁忌

- 禁止使用基础单字节读写!开发一律用缓冲流,效率差距极大

八、IO 流体系思维导图(总结)

IO流

├─ 按数据类型

│ ├─ 字节流(所有文件):InputStream / OutputStream

│ └─ 字符流(纯文本):Reader / Writer

├─ 基础节点流

│ ├─ FileInputStream / FileOutputStream(字节文件读写)

│ └─ FileReader / FileWriter(文本读写)

├─ 高效缓冲流(开发首选)

│ └─ BufferedXXX(自带缓冲区,批量读写)

└─ 转换流(编码处理)

└─ InputStreamReader / OutputStreamWriter(统一编码,解决乱码)

结尾

IO 流是 Java文件操作、框架底层、网络编程的基石,没有复杂逻辑,核心就是分清流的用途、规范关闭资源、优先使用缓冲流。