Skip to content

07-IO 流与 File 类

对应原始资料:JavaSE进阶_day10~day12

一、File 类

java.io.File:文件和目录路径的抽象表示。

1. 构造与常用方法

java
File f = new File("D:/a.txt");
File dir = new File("D:/demo");

f.exists();        // 是否存在
f.isFile();        // 是文件
f.isDirectory();   // 是目录
f.getName();
f.length();        // 字节数
f.getAbsolutePath();
f.lastModified();  // 毫秒时间戳

f.createNewFile();  // 创建文件
f.mkdir();          // 创建单级
f.mkdirs();         // 创建多级目录
f.delete();         // 删除(目录必须为空)
f.renameTo(new File("D:/b.txt"));

2. 遍历目录

java
String[] names = dir.list();
File[] files = dir.listFiles();
// 文件名过滤器
File[] txts = dir.listFiles((d, n) -> n.endsWith(".txt"));

3. 递归遍历(经典)

java
void find(File dir) {
    File[] fs = dir.listFiles();
    if (fs == null) return;
    for (File f : fs) {
        if (f.isFile()) System.out.println(f);
        else find(f);
    }
}

二、IO 流体系

字节流(读写任意文件,.txt/.图片/视频)
├── InputStream
│     ├── FileInputStream
│     ├── BufferedInputStream
│     └── ObjectInputStream(反序列化)
└── OutputStream
      ├── FileOutputStream
      ├── BufferedOutputStream
      └── ObjectOutputStream(序列化)

字符流(只读写纯文本文件,按字符)
├── Reader
│     ├── FileReader
│     ├── BufferedReader(.readLine())
│     └── InputStreamReader(转换流,指定编码)
└── Writer
      ├── FileWriter
      ├── BufferedWriter(.newLine())
      └── OutputStreamWriter

选型规则

  • 纯文本 → 字符流。
  • 图片、视频、未知格式 → 字节流。

三、字节流

FileInputStream / FileOutputStream

java
// 读
try (FileInputStream fis = new FileInputStream("a.txt")) {
    int b;
    while ((b = fis.read()) != -1) System.out.print((char) b);
    // 或一次读一个字节数组
    byte[] buf = new byte[1024];
    int len;
    while ((len = fis.read(buf)) != -1) {
        System.out.println(new String(buf, 0, len));
    }
}

// 写
try (FileOutputStream fos = new FileOutputStream("b.txt")) {
    fos.write(97);
    fos.write("hello".getBytes());
    fos.write("world".getBytes(), 0, 3);
}
// 第二参数 append=true 表示追加模式

文件拷贝

java
try (FileInputStream fis = new FileInputStream("src.jpg");
     FileOutputStream fos = new FileOutputStream("dst.jpg")) {
    byte[] buf = new byte[8192];
    int len;
    while ((len = fis.read(buf)) != -1) fos.write(buf, 0, len);
}

四、字节缓冲流

内部维护 8192 字节缓冲区,大幅提升读写效率。

java
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b"));
bos.write(...);  bos.flush();   // 主动刷新

五、字符流与编码

1. 编码表

  • ASCII → ISO-8859-1 → GBK(中文 2 字节) → Unicode(统一码) → UTF-8(变长)。
  • IDEA 默认 UTF-8。

2. 转换流(指定编码)

java
InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk.txt"), "GBK");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("out.txt"), "UTF-8");

3. FileReader / FileWriter

JDK 11 起 FileReader 可指定编码,等价于转换流简化版。

六、字符缓冲流

java
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
String line;
while ((line = br.readLine()) != null) {   // 一次读一行
    System.out.println(line);
}

BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
bw.write("hello"); bw.newLine();          // 跨平台换行

七、对象序列化

把对象转成字节序列持久化到文件 / 网络传输。

1. 序列化

java
class User implements Serializable {       // 必须实现
    private static final long serialVersionUID = 1L;  // 版本号
    String name;
    transient String password;             // transient 不参与序列化
}

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("u.dat"));
oos.writeObject(user);

2. 反序列化

java
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("u.dat"));
User u = (User) ois.readObject();

注意:

  • 静态成员不会被序列化(属于类)。
  • serialVersionUID 不一致会抛 InvalidClassException
  • 被引用的对象也必须实现 Serializable。

八、其他流(了解)

作用
PrintStream / PrintWriter打印流,System.out 就是 PrintStream
DataInputStream / DataOutputStream读写基本类型(顺序一致)
SequenceInputStream多个流合并
PipedInputStream管道流,线程通信
commons-io 工具包FileUtilsIOUtils(Apache 提供的工具,简化 IO)

九、try-with-resources

JDK 7 自动关流(资源需实现 AutoCloseable):

java
try (FileReader fr = new FileReader("a.txt");
     FileWriter fw = new FileWriter("b.txt")) {
    // 使用
} catch (IOException e) { }
// fr、fw 自动 close()

练习建议

  1. 递归统计某个目录下不同类型文件(.jpg/.txt)的个数。
  2. 字节流拷贝图片、视频,对比单字节 vs 字节数组 vs 缓冲流的速度。
  3. 字符缓冲流实现「读取一个文本文件,按行反转后写到另一个文件」。
  4. List<User> 序列化到文件,再反序列化读回来。
  5. Properties 读取 .properties 配置文件。