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流是一种数据流动的抽象概念,可以想象为数据在源与目标之间流动的管道。这个管道能够:
- 以单向或双向的方式传输数据
- 支持多种数据格式(字节、字符等)
- 提供缓冲机制提高效率
💯IO流的体系
注意:倒数第二层皆为抽象类,其下则为对应的实现类。
- 字节输入流
InputStream
(读字节数据的) - 字节输出流
OutputStream
(写字节数据出去的) - 字符输入流
Reader
(读字符数据的) - 字符输出流
Writer
(写字符数据出去的)
💯IO流的典型应用场景
-
文件操作:读取/写入各种文件(文本、图片、视频等)
- 示例:使用
FileInputStream
读取本地文件内容 - 示例:使用
FileWriter
将日志写入文本文件
- 示例:使用
-
网络通信:
Socket
编程中的数据交换- 示例:通过
Socket
的InputStream/OutputStream
进行网络数据传输
- 示例:通过
-
内存数据操作:对内存中的数据进行IO操作
- 示例:
ByteArrayInputStream/ByteArrayOutputStream
处理内存字节数据
- 示例:
-
设备交互:与各种输入输出设备通信
- 示例:
System.in
读取键盘输入 - 示例:
System.out
输出到控制台
- 示例:
💯IO流的使用步骤
典型的IO流操作流程:
- 创建流对象(建立数据通道)
- 执行读写操作(传输数据)
- 关闭流对象(释放资源)
// 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()
public int read(byte[] buffer)
- 示例:
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
块中的代码总是执行,即使try
或catch
中有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()
public int read(char[] buffer)
示例:
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(); } }}
注意事项:
- 文件路径要正确,可以是绝对路径或相对路径。
- 文件编码要与系统默认编码一致,否则可能出现乱码。
- 对于大文件建议使用
BufferedReader
进行缓冲。 - 使用
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
(输出)。
缓冲流是 “高级流”,通过 装饰者模式 包装“低级流”(如 FileInputStream
、FileReader
),增强其性能。具体实现类:
- 字节缓冲流:
BufferedInputStream
(输入)、BufferedOutputStream
(输出)。 - 字符缓冲流:
BufferedReader
(输入)、BufferedWriter
(输出)。
💯缓冲流的核心原理
- 为什么需要缓冲?
- 想象一下:如果读取16KB的文件,没有缓冲流 时,每次只能读1字节,需要读16384次(磁盘IO 16384次);有缓冲流 时,缓冲流内部自带 8KB缓冲区,只需读2次(16KB ÷ 8KB/次),磁盘IO次数直接砍到1/8000!
- 同理,写入数据时,缓冲流会先把数据存到缓冲区,满了再一次性写入磁盘,同样减少IO操作。
💯字节缓冲流
- 类介绍
BufferedInputStream(InputStream is)
:将低级字节输入流(如FileInputStream
)包装成缓冲输入流。BufferedOutputStream(OutputStream os)
:将低级字节输出流(如FileOutputStream
)包装成缓冲输出流。
- 代码示例:用缓冲流复制图片(字节流适用任意文件)
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(); } }}
- 核心逻辑解析
- 缓冲流的作用:
bis
内部的8KB缓冲区会批量读取文件数据,bos
会批量写入,即使自定义的buffer
只有1KB,底层IO次数仍由8KB决定(性能远胜直接用FileInputStream
)。 - 关闭流:
try-with-resources
会先关高级流(bis
、bos
),再关低级流(fis
、fos
),避免资源泄漏。
💯字符缓冲流
- 类介绍
BufferedReader(Reader r)
:包装低级字符输入流(如FileReader
),特有方法readLine()
可直接读取一行文本。BufferedWriter(Writer w)
:包装低级字符输出流(如FileWriter
),特有方法newLine()
可跨平台换行(自动适配Windows的\\r\\n
和Linux的\\n
)。
- 代码示例:用缓冲流复制文本文件(逐行读写)
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(); } }}
- 核心优势解析
readLine()
的便利:无需手动处理换行符,直接按行读取,适合处理日志、配置文件等文本。newLine()
的智能:自动根据系统生成换行符,避免手动写\\r\\n
导致的跨平台问题。
💯小结
- 性能优先:处理大文件或频繁读写时,必须用缓冲流包装低级流,减少IO损耗。
- 分工明确:
- 字节缓冲流 → 处理二进制文件(图片、视频、exe)。
- 字符缓冲流 → 处理文本文件(.txt、.java、日志)。
- 装饰者模式:缓冲流不改变原有流的功能,只是增强性能,符合“对扩展开放,对修改关闭”的设计原则。
✍️其它流
在Java IO体系中,除了基础的字节流、字符流、缓冲流,还有三类“特殊选手”:字符输入转换流(InputStreamReader) 解决编码乱码,打印流(PrintStream/PrintWriter) 简化输出,数据输出流(DataOutputStream) 精准控制数据类型写入。
💯字符输入转换流(InputStreamReader)
- 核心价值:指定编码解码,解决文本乱码
当文件编码(如GBK)与JVM默认编码(如UTF-8)不一致时,直接用 FileReader
会乱码。InputStreamReader
允许我们手动指定编码,让字节流“正确解码”为字符流。
- 关键构造器
InputStreamReader(InputStream is)
FileReader
效果一致,无法解决乱码,仅作兼容)InputStreamReader(InputStream is, String charset)
\"GBK\"
、\"UTF-8\"
,解决乱码的核心用法)- 代码示例
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)
- 核心价值:更方便的输出,支持自动换行、多数据类型
打印流让输出告别繁琐的 write()
方法,直接用 print()
、println()
输出任意类型(字符串、数字、布尔等),还能自动处理换行。
- PrintStream 关键构造器
PrintStream(OutputStream/File/String)
PrintStream(String fileName, Charset charset)
PrintStream(OutputStream out, boolean autoFlush)
- 代码示例
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(); } }}
- 为什么用打印流?
- 对比
FileOutputStream
的write()
,print()
支持所有数据类型,无需手动转字节。 System.out
本质就是PrintStream
,所以System.out.println()
才这么好用!
💯数据输出流(DataOutputStream)
- 核心价值:按“数据类型”写入,读时可精准还原
普通输出流写入 int
会转成字节(可能丢失类型信息),而 DataOutputStream
会记录数据类型的“元信息”,读时用 DataInputStream
可精准还原(如写入 int
就必须用 readInt()
读取)。
- DataOutputStream 关键方法
writeByte(int v)
writeInt(int v)
writeDouble(double v)
writeUTF(String str)
readUTF()
精准读取)- 代码示例
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 方法顺序读取
- 应用场景
- 存储结构化数据(如游戏存档、配置文件),读时能精准还原类型。
- 对比普通输出流:若用
FileOutputStream
写int
,读时无法区分是int
还是普通字节,而DataOutputStream
能严格保留类型。
💯三类流的对比与选型建议
new InputStreamReader(is, \"GBK\")
print()
、println()
writeInt()
、writeUTF()
💻IO框架
💯什么是框架?
- 定义:Java 框架是预先封装通用功能(如依赖管理、数据访问)、规范开发流程的代码体系,帮开发者规避重复造轮子,聚焦业务逻辑。
- 形式:以
Jar
包提供类库,通过注解、配置文件(如XML
)定义规则,内置设计模式(如Spring
的IOC/AOP
),并开放扩展接口 。
IO框架封装了Java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。
💯导入框架详细步骤
- 创建lib文件夹
在项目根目录下右键点击 -> 选择\"New\" -> 选择\"Directory\" -> 输入文件夹名称\"lib\" -> 点击\"OK\"确认创建。这个文件夹将用于存放项目所需的所有第三方jar包。
- 添加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\'
- 如果项目使用Maven,可在pom.xml中添加:
-
添加为库
在IntelliJ IDEA中: -
右键点击lib文件夹中的commons-io-2.6.jar文件
-
选择\"Add as Library…\"选项
-
在弹出的对话框中:
- 确保\"Level\"选择的是\"Project Library\"
- 勾选\"Add to module\"选项
- 点击\"OK\"确认
-
导入使用
在需要使用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 的复杂流程(如流关闭、缓冲处理、编码转换)封装成简单方法,大幅提升开发效率。
FileUtils
类:文件级操作
copyFile(File srcFile, File destFile)
copyDirectory(File srcDir, File destDir)
deleteDirectory(File directory)
readFileToString(File file, String encoding)
UTF-8
、GBK
,避免乱码)writeStringToFile(File file, String data, String charset, boolean append)
append=true
追加内容,false
覆盖;指定编码)IOUtils
类:流级操作
copy(InputStream is, OutputStream os)
copy(Reader reader, Writer writer)
write(String data, OutputStream os, String charset)
- 代码示例
- 前提:引入依赖(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(); } }}
- 核心优势:和原生 IO 比,好在哪?
copyFile()
一行代码搞定InputStreamReader
)readFileToString()
直接传编码参数