IO流工具-IoUtil
# 📦 IO流工具-IoUtil
IoUtil 是 Hutool 提供的 IO 流操作核心工具类,封装了 JDK 中复杂的 IO 操作,提供了简洁易用的 API,旨在简化各种 IO 场景下的开发工作。
# 🔧 核心功能
| 功能分类 | 主要方法 | 描述 |
|---|---|---|
| 流复制 | copy() | 实现各种流之间的复制 |
| 流读取 | read()、readBytes()、readLines() | 从流中读取内容 |
| 流写入 | write()、writeStrs()、writeUtf8() | 向流中写入内容 |
| 流转换 | toStream()、toReader()、toWriter() | 各种流之间的转换 |
| 流关闭 | closeQuietly()、closeIfPossible() | 安全关闭流 |
| 流比较 | contentEquals()、contentEqualsIgnoreEOL() | 比较两个流的内容 |
| 行迭代 | lineIter() | 提供行遍历器 |
# 🎯 主要方法示例
# 1. 流复制
// 复制InputStream到OutputStream
InputStream in = new FileInputStream("input.txt");
OutputStream out = new FileOutputStream("output.txt");
long copiedBytes = IoUtil.copy(in, out);
IoUtil.closeQuietly(in, out);
// 复制Reader到Writer
Reader reader = new FileReader("input.txt");
Writer writer = new FileWriter("output.txt");
long copiedChars = IoUtil.copy(reader, writer);
IoUtil.closeQuietly(reader, writer);
// 使用自定义缓存大小复制
long copiedBytesWithBuffer = IoUtil.copy(in, out, 8192);
// 复制文件流(使用NIO)
FileInputStream fileIn = new FileInputStream("input.txt");
FileOutputStream fileOut = new FileOutputStream("output.txt");
long copiedFileBytes = IoUtil.copy(fileIn, fileOut);
IoUtil.closeQuietly(fileIn, fileOut);
# 2. 流读取
# 读取为字符串
// 读取UTF-8编码的字符串
InputStream in = new FileInputStream("test.txt");
String content = IoUtil.readUtf8(in);
IoUtil.closeQuietly(in);
// 读取指定编码的字符串
String contentWithCharset = IoUtil.read(in, CharsetUtil.UTF_8);
# 读取为字节数组
// 读取为字节数组,自动关闭流
InputStream in = new FileInputStream("test.txt");
byte[] bytes = IoUtil.readBytes(in);
// 读取指定长度的字节数组,不关闭流
byte[] limitedBytes = IoUtil.readBytes(in, 1024);
# 读取为行集合
// 读取UTF-8编码的行,存入List
InputStream in = new FileInputStream("test.txt");
List<String> lines = IoUtil.readUtf8Lines(in, new ArrayList<>());
IoUtil.closeQuietly(in);
// 读取指定编码的行,存入Set
Set<String> uniqueLines = IoUtil.readLines(in, CharsetUtil.UTF_8, new HashSet<>());
# 按行处理
// 按行处理UTF-8编码的内容
InputStream in = new FileInputStream("test.txt");
IoUtil.readUtf8Lines(in, line -> {
Console.log("Line: " + line);
});
IoUtil.closeQuietly(in);
// 按行处理指定编码的内容
IoUtil.readLines(in, CharsetUtil.UTF_8, line -> {
Console.log("Line: " + line);
});
# 读取对象
// 读取序列化对象
InputStream in = new FileInputStream("object.ser");
Object obj = IoUtil.readObj(in, MyClass.class);
IoUtil.closeQuietly(in);
# 读取到指定标记
// 读取到指定字符
InputStream in = new FileInputStream("test.txt");
FastByteArrayOutputStream out = IoUtil.readToToken(in, '\n');
String line = out.toString();
IoUtil.closeQuietly(in);
// 读取到满足条件的字符
FastByteArrayOutputStream out2 = IoUtil.readTo(in, c -> c == ';');
String contentUntilSemicolon = out2.toString();
# 3. 流写入
# 写入字节数组
// 写入字节数组,不关闭流
OutputStream out = new FileOutputStream("output.txt");
IoUtil.write(out, false, new byte[]{1, 2, 3});
// 写入字节数组,关闭流
IoUtil.writeClose(out, new byte[]{1, 2, 3});
# 写入字符串
// 写入UTF-8编码的字符串,不关闭流
OutputStream out = new FileOutputStream("output.txt");
IoUtil.writeUtf8(out, false, "Hello", " ", "World");
// 写入指定编码的字符串
IoUtil.writeStrs(out, CharsetUtil.UTF_8, false, "Hello", " ", "World");
# 写入对象
// 写入序列化对象
OutputStream out = new FileOutputStream("object.ser");
IoUtil.writeObjects(out, false, new MyClass(), new MyClass());
IoUtil.closeQuietly(out);
# 4. 流转换
# 字符串转流
// 字符串转为UTF-8编码的字节流
ByteArrayInputStream utf8Stream = IoUtil.toUtf8Stream("Hello World");
// 字符串转为指定编码的字节流
ByteArrayInputStream stream = IoUtil.toStream("Hello World", CharsetUtil.UTF_8);
# 文件转流
// File转为InputStream
File file = new File("test.txt");
InputStream fileStream = IoUtil.toStream(file);
// Path转为InputStream
Path path = Paths.get("test.txt");
InputStream pathStream = IoUtil.toStream(path);
# 字节数组转流
// 字节数组转为InputStream
byte[] bytes = {1, 2, 3};
ByteArrayInputStream byteStream = IoUtil.toStream(bytes);
// ByteArrayOutputStream转为InputStream
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(bytes);
ByteArrayInputStream in = IoUtil.toStream(out);
# 转换为缓冲流
// 转换为BufferedInputStream
InputStream in = new FileInputStream("test.txt");
BufferedInputStream bufferedIn = IoUtil.toBuffered(in);
// 转换为BufferedReader
Reader reader = new FileReader("test.txt");
BufferedReader bufferedReader = IoUtil.toBuffered(reader);
// 转换为BufferedOutputStream
OutputStream out = new FileOutputStream("test.txt");
BufferedOutputStream bufferedOut = IoUtil.toBuffered(out);
// 转换为BufferedWriter
Writer writer = new FileWriter("test.txt");
BufferedWriter bufferedWriter = IoUtil.toBuffered(writer);
# 转换为支持标记的流
// 转换为支持mark标记的流
InputStream in = new FileInputStream("test.txt");
InputStream markSupportIn = IoUtil.toMarkSupport(in);
# 转换为回退流
// 转换为PushbackReader
Reader reader = new FileReader("test.txt");
PushbackReader pushbackReader = IoUtil.toPushBackReader(reader, 1024);
// 转换为PushbackInputStream
InputStream in = new FileInputStream("test.txt");
PushbackInputStream pushbackStream = IoUtil.toPushbackStream(in, 1024);
# 5. 流关闭
// 静默关闭多个流
InputStream in1 = new FileInputStream("test1.txt");
InputStream in2 = new FileInputStream("test2.txt");
IoUtil.closeQuietly(in1, in2);
// 关闭实现AutoCloseable接口的对象
AutoCloseable obj = new FileInputStream("test.txt");
IoUtil.closeIfPossible(obj);
// 安全关闭流,抛出IOException
Closeable closeable = new FileInputStream("test.txt");
try {
IoUtil.nullSafeClose(closeable);
} catch (IOException e) {
e.printStackTrace();
}
# 6. 流比较
// 比较两个流的内容是否相同
InputStream in1 = new FileInputStream("test1.txt");
InputStream in2 = new FileInputStream("test2.txt");
boolean isEqual = IoUtil.contentEquals(in1, in2);
IoUtil.closeQuietly(in1, in2);
// 比较两个Reader的内容是否相同
Reader reader1 = new FileReader("test1.txt");
Reader reader2 = new FileReader("test2.txt");
boolean isReaderEqual = IoUtil.contentEquals(reader1, reader2);
IoUtil.closeQuietly(reader1, reader2);
// 比较两个Reader的内容是否相同,忽略换行符
boolean isEqualIgnoreEOL = IoUtil.contentEqualsIgnoreEOL(reader1, reader2);
# 7. 行迭代
// 使用行迭代器遍历流内容
InputStream in = new FileInputStream("test.txt");
LineIter lineIter = IoUtil.lineIter(in, CharsetUtil.UTF_8);
try {
while (lineIter.hasNext()) {
String line = lineIter.nextLine();
Console.log("Line: " + line);
}
} finally {
lineIter.close();
}
// 使用行迭代器遍历Reader
Reader reader = new FileReader("test.txt");
LineIter readerIter = IoUtil.lineIter(reader);
try {
while (readerIter.hasNext()) {
String line = readerIter.nextLine();
Console.log("Line: " + line);
}
} finally {
readerIter.close();
}
# 📋 注意事项
流的关闭:
IoUtil的大多数方法不会自动关闭流,需要手动关闭- 可以使用
closeQuietly()方法静默关闭流,避免异常 - 也可以使用 Java 7 的 try-with-resources 语句自动关闭流
缓冲区大小:
- 默认缓冲区大小为
DEFAULT_BUFFER_SIZE(8192字节) - 可以根据实际需求调整缓冲区大小,提高性能
- 默认缓冲区大小为
编码处理:
- 推荐使用
readUtf8()和writeUtf8()方法处理 UTF-8 编码 - 对于其他编码,使用带编码参数的方法
- 推荐使用
异常处理:
- 所有 IO 异常都被转换为
IORuntimeException,无需显式捕获 - 可以根据需要捕获
IORuntimeException进行处理
- 所有 IO 异常都被转换为
性能优化:
- 对于大文件,推荐使用
copy()方法,它使用了缓冲区优化 - 对于频繁的 IO 操作,考虑使用 NIO 相关方法
- 对于大文件,推荐使用
# 💡 最佳实践
- 使用 try-with-resources:
try (InputStream in = new FileInputStream("test.txt"); OutputStream out = new FileOutputStream("output.txt")) { IoUtil.copy(in, out); }
2. **处理大文件**:
```java
// 使用较大的缓冲区提高性能
IoUtil.copy(in, out, 65536);
- 按行处理大文件:
// 使用行迭代器避免一次性加载整个文件到内存 try (LineIter iter = IoUtil.lineIter(new FileInputStream("large.txt"), CharsetUtil.UTF_8)) { while (iter.hasNext()) { String line = iter.nextLine(); // 处理行 } }
4. **使用 UTF-8 编码**:
```java
// 优先使用 UTF-8 编码
String content = IoUtil.readUtf8(in);
IoUtil.writeUtf8(out, false, "content");
通过 IoUtil,可以大幅简化 IO 操作代码,提高开发效率和代码可读性,同时获得更好的性能。