> 技术文档 > Java IO流:文件操作与数据读写全攻略

Java IO流:文件操作与数据读写全攻略


目录

  • 🚀前言
  • 🤔IO流的概念与应用
    • 💯IO流的基本概念
    • 💯IO流的体系
    • 💯IO流的典型应用场景
    • 💯IO流的使用步骤
  • 🦜字节
    • 💯FileInputStream(文件字节输入流)
    • 💯FileOutputStream(文件字节输出流)
    • 💯文件复制
    • 💯资源释放
  • 🐧字符
    • 💯FileReader(文件字符输入流)
    • 💯FileWriter(文件字符输出流)
  • ⚙️缓冲流
    • 💯缓冲流的体系定位
    • 💯缓冲流的核心原理
    • 💯字节缓冲流
    • 💯字符缓冲流
    • 💯小结
  • ✍️其它流
    • 💯字符输入转换流(InputStreamReader)
    • 💯打印流(PrintStream/PrintWriter)
    • 💯数据输出流(DataOutputStream)
    • 💯三类流的对比与选型建议
  • 💻IO框架
    • 💯什么是框架?
    • 💯导入框架详细步骤
    • 💯Commons-io框架

🚀前言

在这里插入图片描述

大家好!我是 EnigmaCoder

  • 本文介绍了Java IO流的核心概念和典型应用。IO流是编程中处理输入输出的关键机制,主要分为字节流(InputStream/OutputStream)和字符流(Reader/Writer)两大体系。文章详细讲解了FileInputStream和FileOutputStream的使用方法,包括单字节读取、缓冲区读取、文件写入等操作,并提供了文件复制的示例代码。IO流广泛应用于文件操作、网络通信、内存数据处理和设备交互等场景。使用IO流时应遵循创建流对象、执行读写和关闭资源的基本流程,同时需注意资源管理和性能优化。

🤔IO流的概念与应用

IO流(Input/Output Stream)是计算机编程中用于处理输入和输出操作的核心机制。它提供了一种标准化的方式在不同设备和程序之间传输数据。

💯IO流的基本概念

IO流是一种数据流动的抽象概念,可以想象为数据在源与目标之间流动的管道。这个管道能够:

  1. 以单向或双向的方式传输数据
  2. 支持多种数据格式(字节、字符等)
  3. 提供缓冲机制提高效率

💯IO流的体系

在这里插入图片描述

注意:倒数第二层皆为抽象类,其下则为对应的实现类。

  • 字节输入流InputStream(读字节数据的)
  • 字节输出流OutputStream(写字节数据出去的)
  • 字符输入流Reader(读字符数据的)
  • 字符输出流Writer(写字符数据出去的)

💯IO流的典型应用场景

  1. 文件操作:读取/写入各种文件(文本、图片、视频等)

    • 示例:使用FileInputStream读取本地文件内容
    • 示例:使用FileWriter将日志写入文本文件
  2. 网络通信Socket编程中的数据交换

    • 示例:通过SocketInputStream/OutputStream进行网络数据传输
  3. 内存数据操作:对内存中的数据进行IO操作

    • 示例:ByteArrayInputStream/ByteArrayOutputStream处理内存字节数据
  4. 设备交互:与各种输入输出设备通信

    • 示例:System.in读取键盘输入
    • 示例:System.out输出到控制台

💯IO流的使用步骤

典型的IO流操作流程:

  1. 创建流对象(建立数据通道)
  2. 执行读写操作(传输数据)
  3. 关闭流对象(释放资源)
// Java示例:文件复制try (FileInputStream fis = new FileInputStream(\"source.txt\"); FileOutputStream fos = new FileOutputStream(\"target.txt\")) { byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) != -1) { fos.write(buffer, 0, length); }} catch (IOException e) { e.printStackTrace();}

🦜字节流

💯FileInputStream(文件字节输入流)

作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。(内存<===磁盘)

构造器 说明 public FileInputStream(File file) 创建字节输入流管道与源文件接通 public FileOutputStream(String pathname) 创建字节输入流管道与源文件接通 方法名称 说明 public int read() 每次读取一个字节返回,如果发现没有数据可能会返回-1 public int read(byte[] buffer) 每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1
  • 示例:
public class FileInputStreamDemo { public static void main(String[] args) throws Exception { // 创建文件输入流对象,指定要读取的文件路径 // 注意:路径中使用双反斜杠\\\\表示目录分隔符 InputStream is = new FileInputStream(\"file-io\\\\src\\\\test01.txt\"); // 方法一:单字节读取 // 每次读取一个字节,适用于小文件或需要逐字节处理的场景 System.out.println(\"方法一:单字节读取\"); int b; while ((b = is.read()) != -1) { // read()返回-1表示到达文件末尾 System.out.print((char)b); // 将读取的字节转换为字符输出 } // 方法二:字节数组缓冲读取 // 使用缓冲区提高读取效率,适用于大文件读取 System.out.println(\"\\n方法二:缓冲区读取\"); byte[] buffer = new byte[3]; // 创建3字节的缓冲区 int len; // 记录实际读取的字节数 while ((len = is.read(buffer)) != -1) { // 将读取的字节数组转换为字符串,注意只转换实际读取的部分 String str = new String(buffer, 0, len);  System.out.print(str); } // 关闭资源 is.close(); // 必须关闭文件流释放系统资源 }}

两种方法中,每次读取多个字节,可以减少硬盘与内存的交互次数,要比只读取一个字节性能更好,但两者都无法避免读取汉字输出乱码的问题,存在截断汉字字节的可能性。

InputStream拥有如下方法:

方法名称 说明 public byte[] readAllBytes() throws IOException 直接将当前字节输入流对应的文件对象的字节数据装到一个字节数组返回

该方法直接把文件数据全部读取到一个字节数组可以避免乱码,但如果文件太大,创建的字节数组也会很大,可能引起内存溢出。

  • 结论:读取文本适合用字符流,字节流适合做数据的转移,比如:文件复制

💯FileOutputStream(文件字节输出流)

作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去。(内存===>磁盘)

构造器 说明 public FileOutputStream(File file) 创建字节输出流管道与源文件对象接通 public FileOutputStream(String filepath) 创建字节输出流管道与源文件路径接通 public FileOutputStream(File file,boolean append) 创建字节输出流管道与源文件对象接通,可追加数据 public FileOutputStream(String filepath, boolean append) 创建字节输出流管道与源文件路径接通,可追加数据 方法名称 说明 public void write(int a) 写一个字节出去 public void write(byte[] buffer) 写一个字节数组出去 public void write(byte[] buffer,int pos ,int len) 写一个字节数组的一部分出去 public void close() throws IOException 关闭流
public class FileOutputStreamDemo { /** * 演示FileOutputStream的基本用法 * @param args 命令行参数 * @throws Exception 可能抛出IO异常 */ public static void main(String[] args) throws Exception { // 1. 创建文件输出流(覆盖模式) // 注意:如果文件不存在会自动创建,存在则会清空原有内容 // OutputStream os = new FileOutputStream(\"file-io\\\\src\\\\test02.txt\"); // 2. 创建文件输出流(追加模式) // 第二个参数true表示追加模式,不会清空原有内容 OutputStream os = new FileOutputStream(\"file-io\\\\src\\\\test02.txt\", true); // 3. 写入单个字节 os.write(97); // 写入ASCII码97对应的字符\'a\' os.write(\'b\'); // 直接写入字符\'b\' os.write(\"\\r\\n\".getBytes()); // 写入换行符(Windows系统) // 4. 写入字节数组 byte[] bytes = \"我爱你中国\".getBytes(); // 默认使用UTF-8编码 os.write(bytes); // 写入完整字节数组 os.write(\"\\r\\n\".getBytes()); // 再次换行 // 5. 写入字节数组的一部分 os.write(bytes, 0, 3); // 只写入前3个字节(\"我\"字) // 6. 关闭流(重要!) os.close(); // 实际应用场景示例: // - 日志文件记录 // - 数据持久化存储 // - 文件下载功能实现 }}

💯文件复制

文件本质上都是由字节构成,因此使用字节流进行复制能够完整保留所有数据。但需要注意,源文件和目标文件必须保持相同的格式

import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class FileCopy { public static void copyFile(String sourcePath, String targetPath) throws IOException { try (FileInputStream fis = new FileInputStream(sourcePath); FileOutputStream fos = new FileOutputStream(targetPath)) { byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer))=-1) { fos.write(buffer, 0, length); } } } public static void main(String[] args) { try { copyFile(\"source.txt\", \"target.txt\"); System.out.println(\"文件复制完成\"); } catch (IOException e) { System.err.println(\"复制过程中发生错误: \" + e.getMessage()); } }}

使用注意事项:

  • 路径参数:sourcePath和targetPath需包含完整路径信息,支持相对路径和绝对路径。

  • 目标文件存在:若目标文件已存在会被直接覆盖,不存在时会自动创建。

  • 大文件处理:默认缓冲区大小适合常规文件,处理超大文件时可适当增大缓冲区(如8192字节)。

💯资源释放

try-catch-finally 是 Java 中处理异常和确保资源释放的标准方式。该结构确保无论是否发生异常,finally 块中的代码都会被执行,常用于关闭文件、数据库连接、网络连接等资源。

标准格式:

FileInputStream fis = null;try { // 可能抛异常的代码块 // 例如:打开文件、建立数据库连接等操作 fis = new FileInputStream(\"test.txt\"); // 使用资源的操作... } catch (IOException e) { // 异常处理代码 e.printStackTrace(); // 打印异常堆栈信息 // 可以添加其他处理逻辑,如日志记录} finally { // 资源释放代码,确保总是执行 // 例如: if (fis != null) { try { fis.close(); // 关闭文件流 } catch (IOException e) { e.printStackTrace(); } }}

注意事项:

  • finally 块中的代码总是执行,即使trycatch中有return语句。
  • 关闭资源时可能也需要try-catch处理可能的异常。
  • Java 7+推荐使用try-with-resources语法简化资源管理。

try-with-resources
格式:

try ( // 资源声明部分,可声明多个资源,用分号隔开 AutoCloseable resource1 = new SomeResource(); AutoCloseable resource2 = new AnotherResource()) { // 业务逻辑代码 // 可能抛出异常的代码块} catch (SpecificException e) { // 异常处理代码 // 例如:日志记录、错误恢复等} finally { // 可选部分,用于执行无论是否发生异常都需要执行的代码 // 注意:这里不需要手动关闭资源}

注意事项:

  • 资源变量在try-with-resources块中隐式被声明为final
  • Java 9开始,可以在try-with-resources中使用已存在的final/effectively final变量。
  • 如果同时发生多个异常,会压制次要异常,保留主要异常。

🐧字符流

💯FileReader(文件字符输入流)

作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。(内存<===磁盘)

构造器 说明 public FileReader(File file) 创建字符输入流管道与源文件接通 public FileReader(String pathname) 创建字符输入流管道与源文件接通 方法名称 说明 public int read() 每次读取一个字符返回,如果发现没有数据可能会返回-1 public int read(char[] buffer) 每次用一个字符数组去读取数据,返回字符数组读取了多少个字节,如果发现没有数据可读会返回-1

示例:

public class FileReaderDemo { public static void main(String[] args) throws Exception { try( Reader fr =new FileReader(\"file-io\\\\src\\\\tese01.txt\"); ){ char[] chs = new char[3]; int len; while((len = fr.read(chs))!=-1){ String str=new String(chs,0,len); System.out.print(str); } }catch(Exception e){ e.printStackTrace(); } }}

注意事项:

  1. 文件路径要正确,可以是绝对路径或相对路径。
  2. 文件编码要与系统默认编码一致,否则可能出现乱码。
  3. 对于大文件建议使用BufferedReader进行缓冲。
  4. 使用try-with-resources确保资源自动关闭。

💯FileWriter(文件字符输出流)

作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去。

构造器 说明 public FileWriter(File file) 创建字符输出流管道与源文件对象接通 public FileWriter(String filepath) 创建字符输出流管道与源文件路径接通 public FileWriter(File file,boolean append) 创建符输出流管道与源文件对象接通,可追加数据 public FileWriter(String filepath, boolean append) 创建字符输出流管道与源文件路径接通,可追加数据 方法名称 说明 void write(int c) 写一个字符 void write(String str) 写一个字符串 void write(String str,int off,int len) 写一个字符串的一部分 void write(char[] cbuf) 写入一个字符数组 void write(char[] cbuf,int off,int len) 写入字符数组的一部分

示例:

public class FileWriterDemo { public static void main(String[] args) { // 使用try-with-resources语句自动关闭资源 try ( // 创建FileWriter对象,覆盖模式 Writer fw1 = new FileWriter(\"file-io\\\\src\\\\test02.txt\"); // 创建FileWriter对象,追加模式 Writer fw2 = new FileWriter(\"file-io\\\\src\\\\test02.txt\", true) ) { // 1. 写入单个字符 fw1.write(\'a\'); // 写入字符\'a\' fw1.write(98); // 写入ASCII码98对应的字符\'b\' fw1.write(\'我\'); // 写入中文字符\'我\' // 2. 写入字符串 fw1.write(\"java\"); // 写入完整字符串\"java\" // 3. 写入字符串的一部分 // 参数说明:字符串,起始位置,长度 fw1.write(\"java\", 1, 2); // 从索引1开始,写入2个字符(\"av\") // 4. 写入字符数组 char[] chars = \"java\".toCharArray(); fw1.write(chars); // 写入整个字符数组 // 5. 写入字符数组的一部分 // 参数说明:字符数组,起始位置,长度 fw1.write(chars, 1, 2); // 从索引1开始,写入2个字符(\"av\") // 注意:所有写入操作都会先写入缓冲区 // 当缓冲区满、调用flush()或关闭流时,数据才会真正写入文件 //fw.flush(); //fw.close();关闭流包含了刷新 } catch (Exception e) { // 打印异常堆栈信息 e.printStackTrace(); } }}

⚙️缓冲流

在Java IO体系中,缓冲流是提升读写性能的关键武器。它就像给普通IO流加了一个“加速buff”,通过减少磁盘IO操作次数,让数据传输更高效。下面我们就来拆解缓冲流的核心逻辑,结合代码示例掌握 BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter 的用法。

💯缓冲流的体系定位

Java IO流分为 字节流字符流 两大分支:

  • 字节流:处理二进制数据(如图片、视频),核心类是 InputStream(输入)和 OutputStream(输出)。
  • 字符流:处理文本数据(如.txt文件),核心类是 Reader(输入)和 Writer(输出)。

缓冲流是 “高级流”,通过 装饰者模式 包装“低级流”(如 FileInputStreamFileReader),增强其性能。具体实现类:

  • 字节缓冲流BufferedInputStream(输入)、BufferedOutputStream(输出)。
  • 字符缓冲流BufferedReader(输入)、BufferedWriter(输出)。

💯缓冲流的核心原理

  • 为什么需要缓冲?
  • 想象一下:如果读取16KB的文件,没有缓冲流 时,每次只能读1字节,需要读16384次(磁盘IO 16384次);有缓冲流 时,缓冲流内部自带 8KB缓冲区,只需读2次(16KB ÷ 8KB/次),磁盘IO次数直接砍到1/8000!
  • 同理,写入数据时,缓冲流会先把数据存到缓冲区,满了再一次性写入磁盘,同样减少IO操作。

💯字节缓冲流

  1. 类介绍
  • BufferedInputStream(InputStream is):将低级字节输入流(如 FileInputStream)包装成缓冲输入流。
  • BufferedOutputStream(OutputStream os):将低级字节输出流(如 FileOutputStream)包装成缓冲输出流。
  1. 代码示例:用缓冲流复制图片(字节流适用任意文件)
import java.io.*;public class BufferedByteDemo { public static void main(String[] args) { // 1. 定义源文件和目标文件 String source = \"D:/image.jpg\"; String target = \"C:/image_copy.jpg\"; // 2. try-with-resources自动关闭流 try ( // 低级流:直接读文件 FileInputStream fis = new FileInputStream(source); // 包装成缓冲输入流(带8KB缓冲区) BufferedInputStream bis = new BufferedInputStream(fis); FileOutputStream fos = new FileOutputStream(target); BufferedOutputStream bos = new BufferedOutputStream(fos); ) { // 3. 定义缓冲区(从缓冲流的8KB缓冲区里读数据) byte[] buffer = new byte[1024]; // 自定义缓冲区,配合缓冲流使用 int len; // 记录每次读取的字节数 // 4. 循环读写:从bis读入buffer,再写入bos while ((len = bis.read(buffer)) != -1) { bos.write(buffer, 0, len); } System.out.println(\"文件复制完成!\"); } catch (IOException e) { e.printStackTrace(); } }}
  1. 核心逻辑解析
  • 缓冲流的作用bis 内部的8KB缓冲区会批量读取文件数据,bos 会批量写入,即使自定义的 buffer 只有1KB,底层IO次数仍由8KB决定(性能远胜直接用 FileInputStream)。
  • 关闭流try-with-resources 会先关高级流(bisbos),再关低级流(fisfos),避免资源泄漏。

💯字符缓冲流

  1. 类介绍
  • BufferedReader(Reader r):包装低级字符输入流(如 FileReader),特有方法 readLine() 可直接读取一行文本。
  • BufferedWriter(Writer w):包装低级字符输出流(如 FileWriter),特有方法 newLine() 可跨平台换行(自动适配Windows的\\r\\n和Linux的\\n)。
  1. 代码示例:用缓冲流复制文本文件(逐行读写)
import java.io.*;public class BufferedCharDemo { public static void main(String[] args) { String source = \"D:/test.txt\"; String target = \"C:/test_copy.txt\"; try ( FileReader fr = new FileReader(source); BufferedReader br = new BufferedReader(fr); // 缓冲字符输入流 FileWriter fw = new FileWriter(target); BufferedWriter bw = new BufferedWriter(fw); // 缓冲字符输出流 ) { String line; // 逐行读取:br.readLine()返回null表示读完 while ((line = br.readLine()) != null) { bw.write(line); // 写入一行内容 bw.newLine(); // 换行(跨平台安全) } System.out.println(\"文本复制完成!\"); } catch (IOException e) { e.printStackTrace(); } }}
  1. 核心优势解析
  • readLine() 的便利:无需手动处理换行符,直接按行读取,适合处理日志、配置文件等文本。
  • newLine() 的智能:自动根据系统生成换行符,避免手动写 \\r\\n 导致的跨平台问题。

💯小结

  1. 性能优先:处理大文件或频繁读写时,必须用缓冲流包装低级流,减少IO损耗。
  2. 分工明确
    • 字节缓冲流 → 处理二进制文件(图片、视频、exe)。
    • 字符缓冲流 → 处理文本文件(.txt、.java、日志)。
  3. 装饰者模式:缓冲流不改变原有流的功能,只是增强性能,符合“对扩展开放,对修改关闭”的设计原则。

✍️其它流

在Java IO体系中,除了基础的字节流、字符流、缓冲流,还有三类“特殊选手”:字符输入转换流(InputStreamReader) 解决编码乱码,打印流(PrintStream/PrintWriter) 简化输出,数据输出流(DataOutputStream) 精准控制数据类型写入。

💯字符输入转换流(InputStreamReader)

  1. 核心价值:指定编码解码,解决文本乱码

当文件编码(如GBK)与JVM默认编码(如UTF-8)不一致时,直接用 FileReader 会乱码。InputStreamReader 允许我们手动指定编码,让字节流“正确解码”为字符流。

  1. 关键构造器
构造器签名 说明 InputStreamReader(InputStream is)JVM默认编码 解码(和 FileReader 效果一致,无法解决乱码,仅作兼容) InputStreamReader(InputStream is, String charset)指定编码 解码(如 \"GBK\"\"UTF-8\",解决乱码的核心用法)
  1. 代码示例
import java.io.*;public class InputStreamReaderDemo { public static void main(String[] args) { String gbkFilePath = \"D:/gbk_text.txt\"; // GBK编码的文本文件 try ( // 1. 字节流:读取原始字节(不关心编码) FileInputStream fis = new FileInputStream(gbkFilePath); // 2. 转换流:指定GBK编码解码(关键!) InputStreamReader isr = new InputStreamReader(fis, \"GBK\"); // 3. 缓冲流:提升读取效率(可选但推荐) BufferedReader br = new BufferedReader(isr); ) { String line; while ((line = br.readLine()) != null) { System.out.println(\"读取内容:\" + line); // 输出正常中文,无乱码 } } catch (IOException e) { e.printStackTrace(); } }}

💯打印流(PrintStream/PrintWriter)

  1. 核心价值:更方便的输出,支持自动换行、多数据类型

打印流让输出告别繁琐的 write() 方法,直接用 print()println() 输出任意类型(字符串、数字、布尔等),还能自动处理换行。

  1. PrintStream 关键构造器
构造器签名 说明 PrintStream(OutputStream/File/String) 直接关联字节输出流/文件/路径,默认编码(简单场景用) PrintStream(String fileName, Charset charset) 指定输出文件的编码(解决写入乱码) PrintStream(OutputStream out, boolean autoFlush) 自动刷新缓冲区(如System.out就是PrintStream,输出后自动显示)
  1. 代码示例
import java.io.*;import java.nio.charset.StandardCharsets;public class PrintStreamDemo { public static void main(String[] args) { String outputPath = \"D:/print_demo.txt\"; try ( // 1. 字节输出流(基础流) FileOutputStream fos = new FileOutputStream(outputPath); // 2. 打印流:指定UTF-8编码 + 自动刷新 PrintStream ps = new PrintStream(fos, true, StandardCharsets.UTF_8.name()); ) { ps.println(\"Hello,打印流!\"); // 自动换行 ps.print(123); // 输出数字,无需手动转字符串 ps.println(true); // 输出布尔值 } catch (IOException e) { e.printStackTrace(); } }}
  1. 为什么用打印流?
  • 对比 FileOutputStreamwrite()print() 支持所有数据类型,无需手动转字节。
  • System.out 本质就是 PrintStream,所以 System.out.println() 才这么好用!

💯数据输出流(DataOutputStream)

  1. 核心价值:按“数据类型”写入,读时可精准还原

普通输出流写入 int 会转成字节(可能丢失类型信息),而 DataOutputStream 会记录数据类型的“元信息”,读时用 DataInputStream 可精准还原(如写入 int 就必须用 readInt() 读取)。

  1. DataOutputStream 关键方法
方法签名 说明 writeByte(int v) 写入1个字节(byte类型) writeInt(int v) 写入4个字节(int类型) writeDouble(double v) 写入8个字节(double类型) writeUTF(String str) 用UTF-8编码写入字符串(会记录字符串长度,读时用 readUTF() 精准读取)
  1. 代码示例
import java.io.*;public class DataOutputStreamDemo { public static void main(String[] args) { String dataPath = \"D:/data_demo.dat\"; try ( // 1. 字节输出流(基础流) FileOutputStream fos = new FileOutputStream(dataPath); // 2. 数据输出流:包装基础流 DataOutputStream dos = new DataOutputStream(fos); ) { dos.writeUTF(\"Java IO 数据输出流\"); // 写入字符串(带长度信息) dos.writeInt(2024); // 写入年份(4字节) dos.writeDouble(95.5); // 写入成绩(8字节) } catch (IOException e) { e.printStackTrace(); } }}// 拓展:读数据需用 DataInputStream,配合 write 方法顺序读取
  1. 应用场景
  • 存储结构化数据(如游戏存档、配置文件),读时能精准还原类型。
  • 对比普通输出流:若用 FileOutputStreamint,读时无法区分是 int 还是普通字节,而 DataOutputStream 能严格保留类型。

💯三类流的对比与选型建议

流类型 核心解决问题 典型场景 关键API/方法 InputStreamReader 解决编码不匹配导致的文本乱码 读取GBK/UTF-8等编码的文本文件 new InputStreamReader(is, \"GBK\") PrintStream 简化输出操作,支持多类型自动转换 控制台输出、日志文件写入 print()println() DataOutputStream 精准写入数据类型,保留元信息 结构化数据存储(如游戏存档) writeInt()writeUTF()

💻IO框架

💯什么是框架?

  • 定义:Java 框架是预先封装通用功能(如依赖管理、数据访问)、规范开发流程的代码体系,帮开发者规避重复造轮子,聚焦业务逻辑。
  • 形式:以 Jar 包提供类库,通过注解、配置文件(如 XML)定义规则,内置设计模式(如 SpringIOC/AOP),并开放扩展接口 。

IO框架封装了Java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。

💯导入框架详细步骤

  1. 创建lib文件夹

在项目根目录下右键点击 -> 选择\"New\" -> 选择\"Directory\" -> 输入文件夹名称\"lib\" -> 点击\"OK\"确认创建。这个文件夹将用于存放项目所需的所有第三方jar包。

  1. 添加commons-io-2.6.jar文件

有两种方式可以添加jar文件:

  • 方式一:直接下载jar包

    • 访问Maven仓库(https://mvnrepository.com/)
    • 搜索\"commons-io\" -> 选择版本2.6
    • 下载jar文件到本地
    • 将下载的commons-io-2.6.jar文件复制到刚创建的lib文件夹中
  • 方式二:使用Maven/Gradle管理

    • 如果项目使用Maven,可在pom.xml中添加:
      <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version></dependency>
    • 如果使用Gradle,在build.gradle中添加:
      implementation \'commons-io:commons-io:2.6\'
  1. 添加为库
    在IntelliJ IDEA中:

  2. 右键点击lib文件夹中的commons-io-2.6.jar文件

  3. 选择\"Add as Library…\"选项

  4. 在弹出的对话框中:

    • 确保\"Level\"选择的是\"Project Library\"
    • 勾选\"Add to module\"选项
    • 点击\"OK\"确认
  5. 导入使用
    在需要使用Apache Commons IO的Java类中:

// 导入常用类import org.apache.commons.io.FileUtils;import org.apache.commons.io.IOUtils;// 使用示例public class FileDemo { public static void main(String[] args) { // 使用FileUtils读取文件内容 try { String content = FileUtils.readFileToString(new File(\"test.txt\"), \"UTF-8\"); System.out.println(content); } catch (IOException e) { e.printStackTrace(); } }}

💯Commons-io框架

Commons-io 是 Apache 开源组织 提供的 IO 工具库,通过 FileUtils(文件操作)IOUtils(流操作) 两类核心工具,把原生 IO 的复杂流程(如流关闭、缓冲处理、编码转换)封装成简单方法,大幅提升开发效率。

  1. FileUtils 类:文件级操作
方法签名 说明 copyFile(File srcFile, File destFile) 复制单个文件(自动处理流的创建、关闭,无需手动操作) copyDirectory(File srcDir, File destDir) 复制整个文件夹(递归处理子文件/目录,一键实现文件夹迁移) deleteDirectory(File directory) 删除整个文件夹(递归删除所有内容,慎用!建议先备份) readFileToString(File file, String encoding) 读取文件内容为字符串(指定编码,如 UTF-8GBK,避免乱码) writeStringToFile(File file, String data, String charset, boolean append) 写入字符串到文件(append=true 追加内容,false 覆盖;指定编码)
  1. IOUtils 类:流级操作
方法签名 说明 copy(InputStream is, OutputStream os) 复制字节流(如图片、视频,返回复制的字节数,内置缓冲优化) copy(Reader reader, Writer writer) 复制字符流(如文本文件,返回复制的字符数,自动处理编码转换) write(String data, OutputStream os, String charset) 写入字符串到字节流(指定编码,无需手动转字节数组,框架自动处理)
  1. 代码示例
  • 前提:引入依赖(Maven 为例)
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>2.16.1</version> </dependency>
  • 示例 1:用 FileUtils 复制文件 + 读写字符串
import org.apache.commons.io.FileUtils;import java.io.File;import java.io.IOException;public class FileUtilsDemo { public static void main(String[] args) { // 1. 复制文件(source.txt → target.txt) File src = new File(\"source.txt\"); File dest = new File(\"target.txt\"); try { FileUtils.copyFile(src, dest); System.out.println(\"文件复制成功!\"); } catch (IOException e) { e.printStackTrace(); } // 2. 读取文件内容为字符串(UTF-8编码) try { String content = FileUtils.readFileToString(dest, \"UTF-8\"); System.out.println(\"文件内容:\\n\" + content); } catch (IOException e) { e.printStackTrace(); } // 3. 追加内容到文件(GBK编码,避免中文乱码) try { FileUtils.writeStringToFile(dest, \"\\n追加一行内容\", \"GBK\", true); System.out.println(\"内容追加成功!\"); } catch (IOException e) { e.printStackTrace(); } }}
  • 示例 2:用 IOUtils 复制流 + 写入字符串
import org.apache.commons.io.IOUtils;import java.io.*;import java.nio.charset.StandardCharsets;public class IOUtilsDemo { public static void main(String[] args) { // 1. 复制字节流(复制图片:image.jpg → image_copy.jpg) try ( InputStream is = new FileInputStream(\"image.jpg\"); OutputStream os = new FileOutputStream(\"image_copy.jpg\") ) { int bytesCopied = IOUtils.copy(is, os); System.out.println(\"复制了 \" + bytesCopied + \" 字节\"); } catch (IOException e) { e.printStackTrace(); } // 2. 复制字符流(复制文本:text.txt → text_copy.txt) try ( Reader reader = new FileReader(\"text.txt\"); Writer writer = new FileWriter(\"text_copy.txt\") ) { int charsCopied = IOUtils.copy(reader, writer); System.out.println(\"复制了 \" + charsCopied + \" 个字符\"); } catch (IOException e) { e.printStackTrace(); } // 3. 写入字符串到字节流(输出到文件:output.txt) try (OutputStream os = new FileOutputStream(\"output.txt\")) { IOUtils.write(\"Hello Commons-io!\", os, StandardCharsets.UTF_8); System.out.println(\"字符串写入成功!\"); } catch (IOException e) { e.printStackTrace(); } }}
  1. 核心优势:和原生 IO 比,好在哪?
场景 原生 IO 痛点 Commons-io 解决 文件复制 需手动创建流、循环读写、关闭流 copyFile() 一行代码搞定 编码处理 需手动指定编码转换(如 InputStreamReaderreadFileToString() 直接传编码参数 流关闭 需 try-catch 手动关流(易漏关) 框架自动关闭流,无需操心