Java File类 & IO流完全教程

Java File类 & IO流完全教程

从入门到精通,掌握Java文件操作和输入输出流

📚 目录导航

📁 File类介绍

什么是File类?

File类是java.io包中的一个类,它代表文件和目录路径名的抽象表示。File类可以用于创建、删除、重命名文件和目录,以及查询文件属性等操作。

File类构造方法

// 通过路径字符串创建File对象
File file1 = new File("C:/test/file.txt");

// 通过父路径和子路径创建
File file2 = new File("C:/test", "file.txt");

// 通过父File对象和子路径创建
File parent = new File("C:/test");
File file3 = new File(parent, "file.txt");
💡 注意: File类只表示文件或目录的路径,并不代表文件本身的内容。要操作文件内容,需要使用IO流。

🔧 File类常用操作

文件和目录操作

public class FileOperationExample {
  public static void main(String[] args) {
    File file = new File("test.txt");

    // 创建文件
    try {
      if (file.createNewFile()) {
        System.out.println("文件创建成功");
      }
    } catch (IOException e) {
      e.printStackTrace();
    }

    // 文件信息查询
    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());
    System.out.println("是否存在: " + file.exists());
  }
}

目录操作示例

public class DirectoryExample {
  public static void main(String[] args) {
    File dir = new File("myFolder");

    // 创建目录
    if (dir.mkdir()) {
      System.out.println("目录创建成功");
    }

    // 列出目录内容
    File[] files = dir.listFiles();
    if (files != null) {
      for (File f : files) {
        System.out.println(f.getName());
      }
    }
  }
}

🌊 IO流概述

什么是IO流?

IO流(Input/Output Stream)是Java中用于处理输入输出的机制。流可以看作是一组有序的数据序列,从源端流向目的端。

IO流分类

按数据流向

  • 输入流:从源读取数据
  • 输出流:向目标写入数据

按数据类型

  • 字节流:以字节为单位
  • 字符流:以字符为单位
💡 记忆技巧: 字节流用于处理所有类型文件,字符流专门用于处理文本文件。InputStream/OutputStream处理字节,Reader/Writer处理字符。

🔢 字节流 (Byte Streams)

FileInputStream 文件输入流

public class FileInputStreamExample {
  public static void main(String[] args) {
    FileInputStream fis = null;
    try {
      fis = new FileInputStream("test.txt");
      int data;
      // 逐个字节读取文件
      while ((data = fis.read()) != -1) {
        System.out.print((char) data);
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if (fis != null) fis.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}

FileOutputStream 文件输出流

public class FileOutputStreamExample {
  public static void main(String[] args) {
    FileOutputStream fos = null;
    try {
      fos = new FileOutputStream("output.txt");
      String text = "Hello, Java IO!";
      // 将字符串转换为字节数组写入文件
      fos.write(text.getBytes());
      System.out.println("文件写入成功");
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if (fos != null) fos.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}

🔤 字符流 (Character Streams)

FileReader 文件读取器

public class FileReaderExample {
  public static void main(String[] args) {
    FileReader reader = null;
    try {
      reader = new FileReader("test.txt");
      int data;
      // 逐个字符读取文件
      while ((data = reader.read()) != -1) {
        System.out.print((char) data);
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if (reader != null) reader.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}

FileWriter 文件写入器

public class FileWriterExample {
  public static void main(String[] args) {
    FileWriter writer = null;
    try {
      writer = new FileWriter("output.txt");
      String text = "这是使用FileWriter写入的文本";
      writer.write(text);
      System.out.println("文件写入成功");
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if (writer != null) writer.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}

⚡ 缓冲流 (Buffered Streams)

为什么需要缓冲流?

缓冲流通过在内存中创建缓冲区,减少实际的I/O操作次数,从而提高读写效率。每次读取/写入操作都是针对缓冲区,当缓冲区满时才进行实际的I/O操作。

BufferedReader 示例

public class BufferedReaderExample {
  public static void main(String[] args) {
    try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
      String line;
      // 逐行读取文件,效率更高
      while ((line = br.readLine()) != null) {
        System.out.println(line);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

BufferedWriter 示例

public class BufferedWriterExample {
  public static void main(String[] args) {
    try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
      bw.write("第一行内容");
      bw.newLine(); // 换行
      bw.write("第二行内容");
      bw.flush(); // 刷新缓冲区
      System.out.println("文件写入成功");
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

🎯 对象流 (Object Streams)

序列化对象

class Student implements Serializable {
  private static final long serialVersionUID = 1L;
  private String name;
  private int age;

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

  // getter和setter方法...
}

public class ObjectOutputStreamExample {
  public static void main(String[] args) {
    Student student = new Student("张三", 20);
    try (ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("student.dat"))) {
      oos.writeObject(student);
      System.out.println("对象序列化成功");
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

反序列化对象

public class ObjectInputStreamExample {
  public static void main(String[] args) {
    try (ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("student.dat"))) {
      Student student = (Student) ois.readObject();
      System.out.println("姓名: " + student.getName());
      System.out.println("年龄: " + student.getAge());
    } catch (IOException | ClassNotFoundException e) {
      e.printStackTrace();
    }
  }
}

🚀 实战案例

文件复制工具

public class FileCopy {
  public static void copyFile(String source, String target) {
    try (FileInputStream fis = new FileInputStream(source);
         FileOutputStream fos = new FileOutputStream(target)) {
      byte[] buffer = new byte[1024];
      int length;
      // 使用缓冲区提高复制效率
      while ((length = fis.read(buffer)) != -1) {
        fos.write(buffer, 0, length);
      }
      System.out.println("文件复制成功");
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public static void main(String[] args) {
    copyFile("source.txt", "target.txt");
  }
}

配置文件读取器

public class ConfigReader {
  public static Properties readConfig(String filename) {
    Properties props = new Properties();
    try (FileInputStream fis = new FileInputStream(filename)) {
      props.load(fis);
      System.out.println("配置文件加载成功");
    } catch (IOException e) {
      e.printStackTrace();
    }
    return props;
  }

  public static void main(String[] args) {
    Properties config = readConfig("config.properties");
    String username = config.getProperty("username");
    String password = config.getProperty("password");
    System.out.println("用户名: " + username);
    System.out.println("密码: " + password);
  }
}

📋 快速参考

File类常用方法

  • exists() - 判断文件是否存在
  • createNewFile() - 创建新文件
  • mkdir() - 创建目录
  • delete() - 删除文件
  • listFiles() - 列出文件

IO流选择指南

  • 文本文件 → Reader/Writer
  • 二进制文件 → InputStream/OutputStream
  • 需要高效 → 缓冲流
  • 对象存储 → 对象流

💡 最佳实践

资源管理

  • 使用try-with-resources自动关闭流
  • 及时关闭IO资源
  • 处理IO异常
  • 使用缓冲区提高性能

性能优化

  • 选择合适的流类型
  • 使用缓冲流减少I/O操作
  • 合理设置缓冲区大小
  • 批量读写数据

❓ 常见问题

Q: File类和IO流有什么区别?
A: File类用于操作文件元数据(创建、删除、查询属性),IO流用于读写文件内容。
Q: 什么时候用字节流?什么时候用字符流?
A: 字节流用于所有类型文件,字符流专门用于文本文件(能正确处理编码)。
Q: 为什么要使用缓冲流?
A: 缓冲流通过减少实际I/O操作次数来提高性能,特别适合大文件操作。
Q: 什么是序列化?
A: 序列化是将对象转换为字节序列的过程,便于存储或传输。