2395 字
12 min
0

IO流

本文系统讲解 Java IO 流的核心知识,包括输入输出流的基本概念、字节流与字符流的区别与使用场景、缓冲流的性能优化,以及常用 IO 类库和文件操作,帮助你全面掌握 IO 编程。

File 类

  1. File 类位于 java.io 包中,主要用于表示文件和目录路径
  2. 注意:File 对象仅仅是路径名的抽象表示,并不一定对应一个真实存在的文件或目录。
  3. 可以通过 File 类完成对文件/目录的创建、删除、获取属性等操作,但读写文件内容还需要使用 IO 流。
  4. 常见构造方法:
    构造方法说明
    public File(String pathname)根据给定路径名字符串创建一个 File 对象
    public File(String parent, String child)根据父路径和子路径字符串创建一个 File 对象
    public File(File parent, String child)根据父 File 对象和子路径字符串创建一个 File 对象
    Note
    import java.io.File;
     
    public class Main {
      public static void main(String[] args) {
        // 根据路径字符串创建 File 对象
        File file1 = new File("test.txt");
     
        // 根据父路径和子路径创建
        File file2 = new File("/Users/sun", "test.txt");
     
        // 根据父 File 对象和子路径创建
        File parent = new File("/Users/sun");
        File file3 = new File(parent, "test.txt");
     
        // 打印对象信息
        printFileInfo("file1", file1);
        printFileInfo("file2", file2);
        printFileInfo("file3", file3);
      }
     
      private static void printFileInfo(String name, File file) {
        System.out.println("==== " + name + " ====");
        System.out.println("路径: " + file.getPath());
        System.out.println("绝对路径: " + file.getAbsolutePath());
        System.out.println("是否存在: " + file.exists());
        System.out.println("是否是目录: " + file.isDirectory());
        System.out.println("是否是文件: " + file.isFile());
        System.out.println();
      }
    }
     

常用方法

方法签名说明
public String getName()只返回文件或目录的名称,不包含路径。
public String getPath()返回创建 File 对象时传入的路径字符串,不一定是绝对路径。
public String getAbsolutePath()返回绝对路径(会根据当前工作目录补全)。即使文件不存在,也能返回字符串。
public String getParent()返回父路径字符串(可能是相对路径)。若没有父路径则返回 null
public long length()返回文件大小(单位:字节)。目录调用此方法,返回值未指定(通常为 0)。不存在的文件也返回 0
public long lastModified()返回文件最后修改时间(毫秒)。不存在的文件返回 0
public boolean exists()判断文件或目录是否真实存在。常用前置检查,很多方法调用前最好先判断。
public boolean isFile()判断是否是文件。存在且是文件时返回 true,不存在或目录时返回 false
public boolean isDirectory()判断是否是目录。存在且是目录时返回 true,不存在时返回 false
public boolean canRead()判断文件是否可读。结果受系统权限控制。
public boolean canWrite()判断文件是否可写。在只读目录或权限不足时会返回 false
public boolean isHidden()判断文件是否隐藏。不存在的文件返回 false。不同操作系统定义不同(Windows 取决于隐藏属性,Linux/macOS 以 . 开头)。
public boolean createNewFile()创建一个新文件。文件已存在时返回 false。不能自动创建父目录,父目录不存在会抛 IOException
public boolean delete()删除文件或空目录。非空目录删除失败。删除失败时返回 false,不会抛异常。
public boolean mkdir()创建单级目录。父目录不存在时创建失败,返回 false
public boolean mkdirs()创建多级目录。父目录不存在时也会自动创建。
public String[] list()返回目录下所有文件/子目录的名称数组。只能对目录调用,否则返回 null。目录为空时返回空数组 []
public File[] listFiles()返回目录下所有文件/子目录的 File 对象数组。只能对目录调用,否则返回 null。空目录时返回空数组。
Note
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
 
public class Main {
  public static void main(String[] args) throws IOException {
    // 准备测试路径
    File file = new File("test.txt");
    File dir = new File("testDir");
    File dirs = new File("a/b/c");
 
    // 1. 创建文件
    if (!file.exists()) {
      file.createNewFile();
      System.out.println("文件 test.txt 创建成功");
    }
 
    // 2. 获取文件信息
    System.out.println("getName(): " + file.getName());
    System.out.println("getPath(): " + file.getPath());
    System.out.println("getAbsolutePath(): " + file.getAbsolutePath());
    System.out.println("getParent(): " + file.getParent());
    System.out.println("length(): " + file.length() + " 字节");
    System.out.println("lastModified(): " +
                       new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                       .format(new Date(file.lastModified())));
 
    // 3. 判断方法
    System.out.println("exists(): " + file.exists());
    System.out.println("isFile(): " + file.isFile());
    System.out.println("isDirectory(): " + file.isDirectory());
    System.out.println("canRead(): " + file.canRead());
    System.out.println("canWrite(): " + file.canWrite());
    System.out.println("isHidden(): " + file.isHidden());
 
    // 4. 创建目录
    if (!dir.exists()) {
      dir.mkdir();
      System.out.println("目录 testDir 创建成功");
    }
 
    if (!dirs.exists()) {
      dirs.mkdirs();
      System.out.println("多级目录 a/b/c 创建成功");
    }
 
    // 5. 列出目录内容
    File currentDir = new File(".");
    String[] names = currentDir.list();
    System.out.println("当前目录下的文件/目录名称:");
    if (names != null) {
      for (String name : names) {
        System.out.println("  " + name);
      }
    }
 
    File[] files = currentDir.listFiles();
    System.out.println("当前目录下的文件/目录对象:");
    if (files != null) {
      for (File f : files) {
        System.out.println("  " + f.getAbsolutePath());
      }
    }
 
    // 6. 删除文件和目录(注意:delete() 不能删除非空目录)
    if (file.delete()) {
      System.out.println("文件 test.txt 删除成功");
    }
    if (dir.delete()) {
      System.out.println("目录 testDir 删除成功");
    }
    if (dirs.delete()) {
      System.out.println("目录 a/b/c 删除成功(如果是空目录)");
    }
  }
}
 

File 过滤器

  1. 在 Java 中,File 类提供了过滤器功能,用于筛选目录下的文件或文件夹。通过过滤器,我们可以控制 listFiles()list() 方法返回的文件集合。

  2. listFiles() 可以接受两种类型的过滤器:

    • FileFilter:接受一个 File 对象作为参数,返回 boolean,决定是否包含该文件或目录。
    • FilenameFilter:接受两个参数,第一个是当前目录的 File 对象,第二个是文件名(字符串),返回 boolean,决定是否包含该文件或目录。
  3. 过滤器的使用:

    方法描述
    File[] listFiles(FileFilter filter)使用 FileFilter 过滤文件或目录
    File[] listFiles(FilenameFilter filter)使用 FilenameFilter 过滤文件或目录
    String[] list(FilenameFilter filter)返回符合 FilenameFilter 条件的文件名数组
    import java.io.File;
    import java.io.FileFilter;
    import java.io.FilenameFilter;
                
    public class Main {
        public static void main(String[] args) {
            File dir = new File("/");
                
            // 使用 FileFilter 过滤器:只显示目录
            File[] directories = dir.listFiles(new FileFilter() {
                @Override
                public boolean accept(File file) {
                    return file.isDirectory();
                }
            });
            System.out.println("所有目录:");
            for (File f : directories) {
                System.out.println(f.getName());
            }
                
            // 使用 FilenameFilter 过滤器:只显示 .txt 文件
            File[] txtFiles = dir.listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    return name.endsWith(".txt");
                }
            });
            System.out.println("所有 .txt 文件:");
            for (File f : txtFiles) {
                System.out.println(f.getName());
            }
                
            // 使用 Lambda 表达式简化
            File[] javaFiles = dir.listFiles(f -> f.getName().endsWith(".java"));
            System.out.println("所有 .java 文件:");
            for (File f : javaFiles) {
                System.out.println(f.getName());
            }
        }
    }
                

IO 流概述

  1. 输入(Input):指程序从外部系统获取数据。核心含义是“读”,例如从文件、网络、数据库或内存中读取数据。
  2. 输出(Output):指程序将数据输出到外部系统。核心含义是“写”,例如将数据写入文件、网络连接或控制台。
  3. 数据源(Data Source):提供数据的媒介,可以是文件、数据库、内存、网络、外部设备等。
  4. 流的概念:流是一种有序的数据传输通道,程序通过流可以连续地读取或写入数据。
  5. 流的特点
    • 单向性:数据在流中只能单向传输,输入流从外部到程序,输出流从程序到外部。
    • 有序性:数据按顺序读写,不能跳跃访问(除非使用随机访问类如 RandomAccessFile)。
    • 连接性:流通常连接一个具体的数据源或目的地,通过流对象操作数据源。
  6. 常见场景
    • 从磁盘文件读取文本内容(InputStream/FileReader)
    • 将程序输出写入日志文件(OutputStream/FileWriter)
    • 网络通信(Socket InputStream/OutputStream)
    • 数据库读写(通过流读取 Blob、Clob 等二进制或字符数据)

IO 流的分类

  1. 按流的方向:
    • 输入流(Input Stream):数据从外部流向程序,典型类:InputStreamReader
      • 示例:FileInputStream fis = new FileInputStream("data.txt");
    • 输出流(Output Stream):数据从程序流向外部,典型类:OutputStreamWriter
      • 示例:FileOutputStream fos = new FileOutputStream("data.txt");

  1. 按处理的数据单元:

    • 字节流(Byte Stream):以字节为单位读写数据。适用于所有类型文件,包括文本、图片、音视频。 典型类:InputStreamOutputStream及其子类。

    • 字符流(Character Stream):以字符为单位读写数据。专门用于文本文件,自动处理字符编码。 典型类:ReaderWriter及其子类。


  1. 按处理对象不同:

    • 节点流(Node Stream / 低级流):直接连接到数据源或目的地。 例如:FileInputStreamFileOutputStream

    • 处理流(Filter / 包装流):不直接连接数据源,而是包装其他流提供增强功能,例如缓冲、加密、压缩、对象序列化。 例如:BufferedReaderBufferedOutputStreamDataInputStream

IO 流体系结构

image-20250921211119560

字节流

OutputStream

FileOutputStream

InputStream

FileInputStream

字符流

Writer

FileWriter

Reader

FileReader

缓冲流

字节缓冲流

字符缓冲流

转换流

InputStreamReader

OutputStreamWriter

打印流

PrintStream

PrintWriter

标准输入 / 输出

数据流

DataOutputStream

DataInputStream

对象流

ObjectOutputStream

ObjectInputStream

序列化和反序列化

transient 关键字

字节数组流

ByteArrayOutputStream

ByteArrayInputStream

对象克隆

浅拷贝

深拷贝

配置文件读取

Properties

ResourceBundle

NIO

相关文章

评论区