流与NIO
本课学习Java的流式IO和NIO,了解更底层的文件操作方式。
IO流体系
TEXT
输入流(读取)
InputStream(字节输入流)
├── FileInputStream(文件)
├── BufferedInputStream(缓冲)
├── ByteArrayInputStream(字节数组)
└── DataInputStream(基本类型)
Reader(字符输入流)
├── FileReader(文件)
├── BufferedReader(缓冲)
└── InputStreamReader(转换)
输出流(写入)
OutputStream(字节输出流)
├── FileOutputStream(文件)
├── BufferedOutputStream(缓冲)
└── DataOutputStream(基本类型)
Writer(字符输出流)
├── FileWriter(文件)
├── BufferedWriter(缓冲)
└── OutputStreamWriter(转换)
字节流
FileInputStream读取
JAVA
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("test.txt")) {
int data;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileOutputStream写入
JAVA
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("output.txt")) {
String text = "Hello, World!";
fos.write(text.getBytes());
System.out.println("写入成功");
} catch (IOException e) {
e.printStackTrace();
}
}
}
示例:字节流复制文件
JAVA
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteCopy {
public static void copy(String src, String dest) throws IOException {
try (FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(dest)) {
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 {
copy("source.txt", "dest.txt");
System.out.println("复制完成");
} catch (IOException e) {
e.printStackTrace();
}
}
}
缓冲流
缓冲流提高IO效率,减少磁盘访问次数。
BufferedInputStream/BufferedOutputStream
JAVA
import java.io.*;
public class BufferedStreamDemo {
public static void main(String[] args) throws IOException {
// 写入
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("buffered.txt"))) {
for (int i = 0; i < 1000; i++) {
bos.write(("Line " + i + "\n").getBytes());
}
}
// 读取
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("buffered.txt"))) {
byte[] buffer = new byte[1024];
int length;
while ((length = bis.read(buffer)) != -1) {
System.out.write(buffer, 0, length);
}
}
}
}
数据流
DataInputStream/DataOutputStream可以读写基本类型。
示例:数据流
JAVA
import java.io.*;
public class DataStreamDemo {
public static void main(String[] args) throws IOException {
// 写入
try (DataOutputStream dos = new DataOutputStream(
new FileOutputStream("data.dat"))) {
dos.writeInt(100);
dos.writeDouble(3.14);
dos.writeUTF("Hello");
}
// 读取
try (DataInputStream dis = new DataInputStream(
new FileInputStream("data.dat"))) {
int i = dis.readInt();
double d = dis.readDouble();
String s = dis.readUTF();
System.out.println("int: " + i); // 100
System.out.println("double: " + d); // 3.14
System.out.println("string: " + s); // Hello
}
}
}
NIO(New IO)
Java NIO提供更高效的IO操作。
Path接口
JAVA
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathDemo {
public static void main(String[] args) {
Path path = Paths.get("/home/user/test.txt");
System.out.println("文件名:" + path.getFileName()); // test.txt
System.out.println("父目录:" + path.getParent()); // /home/user
System.out.println("根目录:" + path.getRoot()); // /
System.out.println("路径数:" + path.getNameCount()); // 3
}
}
Files工具类
JAVA
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
public class FilesDemo {
public static void main(String[] args) throws IOException {
Path path = Paths.get("test.txt");
// 判断
System.out.println("是否存在:" + Files.exists(path));
System.out.println("是否是文件:" + Files.isRegularFile(path));
System.out.println("是否可读:" + Files.isReadable(path));
// 读取所有行
List<String> lines = Files.readAllLines(path);
lines.forEach(System.out::println);
// 读取为字节数组
byte[] bytes = Files.readAllBytes(path);
System.out.println("大小:" + bytes.length);
// 写入
Files.write(Paths.get("output.txt"), "Hello".getBytes());
// 创建目录
Files.createDirectories(Paths.get("newdir/subdir"));
// 复制
Files.copy(Paths.get("source.txt"), Paths.get("dest.txt"));
// 移动
Files.move(Paths.get("old.txt"), Paths.get("new.txt"));
// 删除
Files.deleteIfExists(Paths.get("temp.txt"));
}
}
文件属性
JAVA
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
public class FileAttributes {
public static void main(String[] args) throws IOException {
Path path = Paths.get("test.txt");
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println("大小:" + attrs.size());
System.out.println("创建时间:" + attrs.creationTime());
System.out.println("修改时间:" + attrs.lastModifiedTime());
System.out.println("是否是目录:" + attrs.isDirectory());
System.out.println("是否是文件:" + attrs.isRegularFile());
}
}
文件遍历(NIO)
JAVA
import java.io.IOException;
import java.nio.file.*;
import java.util.stream.Stream;
public class NIODirectoryWalk {
public static void main(String[] args) throws IOException {
Path dir = Paths.get(".");
// 遍历目录
try (Stream<Path> stream = Files.list(dir)) {
stream.forEach(path -> {
String type = Files.isDirectory(path) ? "[目录]" : "[文件]";
System.out.println(type + " " + path.getFileName());
});
}
// 递归遍历
try (Stream<Path> stream = Files.walk(dir, 3)) { // 最多3层
stream.forEach(path -> System.out.println(path));
}
// 查找文件
try (Stream<Path> stream = Files.find(dir, 10,
(path, attrs) -> attrs.isRegularFile() && path.toString().endsWith(".txt"))) {
stream.forEach(System.out::println);
}
}
}
IO vs NIO
| 特性 | IO | NIO |
|---|---|---|
| 模型 | 面向流 | 面向缓冲区 |
| 阻塞 | 阻塞IO | 非阻塞IO |
| 选择器 | 无 | 有 |
| API | 较旧 | 较新 |
选择建议
| 场景 | 推荐 |
|---|---|
| 简单文件读写 | Files工具类 |
| 大文件处理 | 缓冲流 |
| 高并发网络 | NIO |
| 旧代码维护 | IO流 |
❓ 常见问题
Q 字节流和字符流怎么选?
A 文本文件用字符流,二进制文件用字节流。
Q 缓冲流有什么好处?
A 减少磁盘访问次数,提高IO效率。
Q NIO比IO快吗?
A 不一定。NIO主要优势是非阻塞和选择器,简单文件操作差异不大。
📖 小节
- IO流分为字节流和字符流
- 缓冲流提高IO效率
- NIO提供更高效的文件操作
- Files工具类简化文件操作
📝 作业
- 文件比较: 比较两个文件是否相同
- 大文件处理: 分块读取大文件,统计行数
- 目录同步: 将一个目录同步到另一个目录
下一课
下一课我们将学习 正则与JSON,了解字符串处理的高级技巧。



