跳转至

IO流

📖 章节简介

本章将介绍Java的IO流操作,包括文件读写、字节流和字符流的使用。

Java IO流体系概览

上图对比了字节流与字符流两大体系,帮助快速选择合适的读写方案。

📁 文件操作

1. File类

Java
// File类使用
import java.io.File;
import java.io.IOException;

public class FileExample {
    public static void main(String[] args) throws IOException {
        // 创建File对象
        File file = new File("test.txt");

        // 创建文件
        if (!file.exists()) {
            boolean created = file.createNewFile();
            System.out.println("文件创建: " + created);
        }

        // 创建目录
        File dir = new File("testdir");
        if (!dir.exists()) {
            boolean created = dir.mkdir();
            System.out.println("目录创建: " + created);
        }

        // 获取文件信息
        System.out.println("\n文件信息:");
        System.out.println("文件名: " + file.getName());
        System.out.println("路径: " + file.getPath());
        System.out.println("绝对路径: " + file.getAbsolutePath());
        System.out.println("大小: " + file.length() + "字节");
        System.out.println("可读: " + file.canRead());
        System.out.println("可写: " + file.canWrite());
        System.out.println("是否文件: " + file.isFile());
        System.out.println("是否目录: " + file.isDirectory());

        // 列出目录内容
        File currentDir = new File(".");
        System.out.println("\n当前目录内容:");
        String[] files = currentDir.list();
        for (String f : files) {
            System.out.println(f);
        }

        // 删除文件
        if (file.exists()) {
            boolean deleted = file.delete();
            System.out.println("\n文件删除: " + deleted);
        }
    }
}

🔄 字节流

1. FileInputStream和FileOutputStream

Java
// 字节流
import java.io.*;

public class ByteStreamExample {
    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) {
            System.out.println("写入失败: " + e.getMessage());
        }

        // 读取文件
        try (FileInputStream fis = new FileInputStream("output.txt")) {
            int data;
            System.out.println("\n读取内容:");
            while ((data = fis.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            System.out.println("读取失败: " + e.getMessage());
        }

        // 缓冲读写
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("output.txt"));
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.txt"))) {

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            System.out.println("\n\n文件复制成功");
        } catch (IOException e) {
            System.out.println("复制失败: " + e.getMessage());
        }
    }
}

2. DataInputStream和DataOutputStream

Java
// 数据流
import java.io.*;

public class DataStreamExample {
    public static void main(String[] args) {
        // 写入数据
        try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.dat"))) {
            dos.writeInt(100);
            dos.writeDouble(3.14);
            dos.writeUTF("Hello");
            dos.writeBoolean(true);
            System.out.println("数据写入成功");
        } catch (IOException e) {
            System.out.println("写入失败: " + e.getMessage());
        }

        // 读取数据
        try (DataInputStream dis = new DataInputStream(new FileInputStream("data.dat"))) {
            int intValue = dis.readInt();
            double doubleValue = dis.readDouble();
            String stringValue = dis.readUTF();
            boolean booleanValue = dis.readBoolean();

            System.out.println("\n读取数据:");
            System.out.println("int: " + intValue);
            System.out.println("double: " + doubleValue);
            System.out.println("String: " + stringValue);
            System.out.println("boolean: " + booleanValue);
        } catch (IOException e) {
            System.out.println("读取失败: " + e.getMessage());
        }
    }
}

📝 字符流

1. FileReader和FileWriter

Java
// 字符流
import java.io.*;

public class CharStreamExample {
    public static void main(String[] args) {
        // 写入文件
        try (FileWriter writer = new FileWriter("text.txt")) {
            writer.write("Hello, World!\n");
            writer.write("这是一个文本文件。");
            System.out.println("写入成功");
        } catch (IOException e) {
            System.out.println("写入失败: " + e.getMessage());
        }

        // 读取文件
        try (FileReader reader = new FileReader("text.txt")) {
            int data;
            System.out.println("\n读取内容:");
            while ((data = reader.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            System.out.println("读取失败: " + e.getMessage());
        }

        // 缓冲读写
        try (BufferedReader br = new BufferedReader(new FileReader("text.txt"));
             BufferedWriter bw = new BufferedWriter(new FileWriter("copy.txt"))) {

            String line;
            System.out.println("\n\n逐行读取:");
            while ((line = br.readLine()) != null) {
                System.out.println(line);
                bw.write(line);
                bw.newLine();
            }
            System.out.println("文件复制成功");
        } catch (IOException e) {
            System.out.println("复制失败: " + e.getMessage());
        }
    }
}

2. PrintWriter

Java
// PrintWriter使用
import java.io.*;

public class PrintWriterExample {
    public static void main(String[] args) {
        try (PrintWriter pw = new PrintWriter(new FileWriter("print.txt"))) {
            // 写入各种类型的数据
            pw.println("Hello, World!");
            pw.printf("姓名: %s, 年龄: %d%n", "张三", 25);
            pw.printf("成绩: %.2f%n", 95.5);
            pw.print("这是最后一行");

            System.out.println("写入成功");
        } catch (IOException e) {
            System.out.println("写入失败: " + e.getMessage());
        }
    }
}

🎯 对象序列化

1. Serializable接口

Java
// 可序列化类
import java.io.Serializable;

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;

    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

// 序列化和反序列化
import java.io.*;

public class SerializationExample {
    public static void main(String[] args) {
        // 序列化对象
        Person person = new Person("张三", 25);

        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.dat"))) {
            oos.writeObject(person);
            System.out.println("对象序列化成功");
        } catch (IOException e) {
            System.out.println("序列化失败: " + e.getMessage());
        }

        // 反序列化对象
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.dat"))) {
            Person deserializedPerson = (Person) ois.readObject();
            System.out.println("\n对象反序列化成功");
            System.out.println("反序列化对象: " + deserializedPerson);
        } catch (IOException | ClassNotFoundException e) {
            System.out.println("反序列化失败: " + e.getMessage());
        }
    }
}

💡 最佳实践

1. 资源管理

Java
// 资源管理最佳实践
public class ResourceManagement {
    // ✅ 好的做法:使用try-with-resources
    public void readFile1() {
        try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("读取失败");
        }
    }

    // ❌ 不好的做法:手动关闭资源
    public void readFile2() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("file.txt"));
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("读取失败");
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    System.out.println("关闭失败");
                }
            }
        }
    }
}

2. 性能优化

Java
// IO性能优化
public class IOOptimization {
    // ✅ 好的做法:使用缓冲流
    public void copyFile1() {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("input.txt"));
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"))) {

            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            System.out.println("复制失败");
        }
    }

    // ❌ 不好的做法:不使用缓冲流
    public void copyFile2() {
        try (FileInputStream fis = new FileInputStream("input.txt");
             FileOutputStream fos = new FileOutputStream("output.txt")) {

            int data;
            while ((data = fis.read()) != -1) {
                fos.write(data);
            }
        } catch (IOException e) {
            System.out.println("复制失败");
        }
    }
}

📝 练习题

基础题

  1. Java的IO流有哪些类型?
  2. 字节流和字符流有什么区别?
  3. 如何使用try-with-resources?

进阶题

  1. 实现文件复制功能。
  2. 使用缓冲流提高IO性能。
  3. 实现对象序列化。

实践题

  1. 创建一个文本编辑器。
  2. 实现一个文件管理工具。
  3. 构建一个简单的日志系统。

📚 推荐阅读

🔗 下一章

多线程 - 学习Java的多线程编程。