IO 流是 Java 开发中非常重要的一个内容,掌握了 IO 流的分类与使用对Java 程序员来说至关重要,最近发现有很多面试者对 Java IO 的理解没有形成体系,只知道其中的一些概念名词,不知道其具体用法。这个 Java IO 的系列文章,希望可以让更多的同学快速掌握 IO 流的使用。

1

初识 Java IO

深入探索Java的File类:文件操作的基石!_System

Java IO 操作主要指的是使用Java进行输入、输出操作,Java 中的所有 IO 操作类都存放在 java.io 包中,在开发时需要导入此包。

在 Java 程序中,对于数据的输入、输出操作以流(stream)的方式进行,Java 提供了种类丰富的“流”类,java.io 包中重要的类有5个:File、InputStream、OutputStream、Reader、Writer。用来处理不同种类的数据,在程序开发过程中通过标准的代码进出数据的输入或输出操作。

深入探索Java的File类:文件操作的基石!_开发语言_02

以程序为中心,从文件或者网络上读取到程序中就用输入流,从程序中写出到文件或者网络上就用输出流。

2

文件操作 File 类

深入探索Java的File类:文件操作的基石!_System_03

1、File 类的基本介绍

File 类是文件和目录路径名的抽象表示,一个 File 对象的建立不等于创建了一个文件或者目录,而是指与文件或者目录建立了联系,通过 File 类的对象可以访问文件的属性、创建空文件和目录、以及删除文件和目录等操作。

2、File 类的两个常量和路径的三种表示形式

File.pathSeparator 表示系统默认路径分隔符,Windows 中使用“;”表示,Linux中使用“:”表示;File.separator 表示系统默认名称分隔符,Windows 中使用“\”表示,Linux中使用“/”表示。

Windows 中文件路径的表示方式用“\”来表示,在 Java 中需要通过转移字符“\\”来表示;Linux 中文件路径表示方式用“/”来表示,当在程序里动态生成文件路径的时候可以使用系统默认名称分隔符 File.separator 来表示。

在开发中推荐大家使用“”/”来做目录名称的分隔符,不管是什么系统都可以使用比如:“D:/Download/image/tomcat.png”。

@Test
  public void test2()
    // 路径分隔符 windows(;) linux(:)
    System.out.println(File.pathSeparator); 
    // 名称分隔符 windows(\) linux(/)
    System.out.println(File.separator); 
    // 路径的几种表示形式
    // windows 的方式
    String path = "D:\\Download\\image\\tomcat.png"; 
    // 动态生成推荐使用这种方式
    path = "D:" + File.separator + "Download" + File.separator + "image" + File.separator + "tomcat.png"; 
    // 推荐使用的方式,什么平台都能用
    path = "D:/Download/image/tomcat.png"; 
    System.out.println(path);
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

3、使用 File 类进行文件的判断操作

我们在操作文件的时候,经常会用到文件的判断操作,常用的判断操作有:文件或目录是否存在、是否是文件、是否是文件夹、获取文件的长度等等。

@Test
  public void test3() {
    String path = "D:/Download/image/tomcat.png";
    File file = new File(path);  // 建立与文件的联系
    System.out.println("文件是否存在:" + file.exists());
    System.out.println("文件是否是文件:" + file.isFile());
    System.out.println("文件是否是文件夹:" + file.isDirectory());
    // 返回字节数,如果是文件夹则读不出来长度
    System.out.println("文件的长度是:" + file.length());
    System.out.println("文件是否可写:" + file.canWrite());
    System.out.println("文件是否可读:" + file.canRead());
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

4、使用 File 类进行文件的创建与删除

文件的创建操作用 createNewFile() 方法,文件不存在则创建新文件,存在则返回 false;文件的删除用 delete() 方法,文件不存在返回 false;在开发中,一般创建和删除文件时都会判断一下文件是否存在。

@Test
  public void test4() throws IOException, InterruptedException {
    String path = "D:/Download/image/tomcat.jpg";
    File file = new File(path); // 建立文件的联系
    if (!file.exists()) {
      boolean flag = file.createNewFile(); // 文件不存在则创建新文件,存在则返回false
      System.out.println(flag ? "文件创建成功" : "文件创建失败");
    }
    if (file.exists()) {
      boolean flag = file.delete(); // 文件不存在返回false
      System.out.println(flag ? "文件删除成功" : "文件删除失败");
    }
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

5、使用 File 类进行目录的操作

目录的创建操作方法有两个,一是 mkdir() 方法,只有父目录存在的情况下才能创建成功;二是 mkdirs() 方法,如果父目录不存在则可把父目录一起创建出来。

目录的删除依然用 delete() 方法,如果目录下面有内容则返回 false;在开发中,一般使用 mkdirs() 方法创建目录。

@Test
  public void test5() throws IOException, InterruptedException {
    // 本地存在pic目录,但是没有photo和2020目录
    String path = "D:/Download/image/pic/photo/2020";
    File file = new File(path);
    System.out.println(file.mkdir()); // false
    System.out.println(file.mkdirs()); // true
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

6、使用 File 类列出指定目录下的文件

在日常开发中,列出目录下的文件这个功能经常会用到,用 File[] listFiles() 方法可以列出目录下的文件或者文件夹,返回的是文件数组。通过循环遍历返回的文件数组就可以获取到每一个文件或者文件夹。listFiles() 方法使用得比较多。

还有一个 String[] list() 方法,它可以列出目录下的文件或者文件夹的名称,这个在开发中不常用。

@Test
  public void test6() {
    String path = "D:/Download/txt";
    File file = new File(path);
    if (file.exists()) {
      // 列出指定目录下的文件或目录的名称字符串数组,不常用
      String[] fileNmaes = file.list();
      System.out.println(Arrays.deepToString(fileNmaes));
      // 列出指定目录下的文件或目录的File对象数组,常用方法
      File[] files = file.listFiles();
      if (files != null) {
        for (File f : files) {
          System.out.println(f);
        }
      }
    }
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
程序运行输出结果:
[123.txt, txt1]
D:\Download\txt\123.txt
D:\Download\txt\txt1
  • 1.
  • 2.
  • 3.
  • 4.

7、综合案例:列出指定目录下的全部内容

列出指定目录下的全部内容和列出指定目录下的文件,区别在于:指定目录下可能存在文件,也可能存在文件夹,子文件夹里也可能存在文件和文件夹。因此需要使用递归的方法完成。

开发思路:首先判断指定目录是否是目录,如果是目录的话,通过 listFiles() 方法获取该目录下的文件或者文件夹,循环取出 File 对象,调用递归方法完成文件路径的输出。

递归方法:递归方法必须要有结束的条件,同时要求递归的函数体内要调用自己。

@Test
  public void test7() {
    String path = "D:/Download/txt";
    File file = new File(path);
    print(file);
  }


  // 递归方法输出指定目录下的文件内容
  public static void print(File file) {
    if (file != null && file.exists()) {
      if (file.isDirectory()) {
        // 如果是目录的话,首先输出路径,然后继续获取该目录下的内容
        System.out.println(file);
        File[] files = file.listFiles();
        if (files != null) { // for循环前判空是个良好的开发习惯
          for (File f : files) {
            print(f); // 递归的函数体内要调用自己
          }
        }
      } else {// 直接打印文件的绝对路径,也就是递归结束的条件
        System.out.println(file);
      }
    }
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

File 类是 Java IO 操作最基础的类,也是唯一的与文件产生关系的类,在所有 IO 操作之前都需要通过 File 类创建文件对象,从而与要操作的文件路径建立联系,之后才能通过选择具体的 IO 流进行文件的操作。