【Java|基础篇】File类和IO流

文章目录

  • 1.File类
  • 2.流的概念
  • 3.InputStream
  • 4.OutputStream
  • 5.Reader
  • 6.Writer
  • 7.使用Scanner进行读文件
  • 8.使用PrintWriter写文件
  • 9.close()方法
  • 10.flush()方法
  • 10.总结

在这里插入图片描述

1.File类

File类是Java中用于表示文件或目录的类。它提供了一些方法来操作文件和目录的属性和内容,可以进行文件的创建、删除、重命名等操作。

File类可以用于表示磁盘上的实际文件或目录,也可以表示一个虚拟的文件或目录。File对象可以通过路径来创建,路径可以是绝对路径或相对路径。

  • 绝对路径(Absolute Path):绝对路径是从文件系统的根目录开始描述文件或目录的位置。它包含了完整的路径信息,从根目录一直到目标文件或目录的全路径。在Windows中,绝对路径以盘符(例如C:\)开头;在Unix/Linux系统中,绝对路径以斜杠(/)开头。

  • 相对路径(Relative Path):相对路径是相对于当前工作目录或引用文件所在位置的路径。它指定文件或目录相对于当前位置的位置关系。相对路径没有从根目录开始的完整路径,而是通过使用“.”(当前目录)和“…”(上级目录)等符号来描述位置关系。

创建File类对象:

File file = new File("文件路径(绝对/相对)");
// 此处的文件路径不要要求一定存在

File类中的常用方法:

方法 描述
getParent() 获取文件的父目录
getName() 获取文件的名字
getPath() 获取文件的路径
getAbsolutePath() 获取绝对路径
getCanonicalPath() 获取标准的绝地路径。
createNewFile() 创建文件
exists() 判断文件是否存在
delete() 删除文件
mkdir() 创建目录(与src同一级)
mkdirs() 创建多级目录
isDirectory() 判断是否为目录
isFile() 是否为文件
renameTo(File dest) 重命名
list() 返回当前目录下所有文件名

上述都是一些获取文件和目录的信息以及增删等操作. 接下来介绍一些文件的读写操作.

2.流的概念

在Java的IO操作中,流(Stream)是指数据的传输管道。它将程序与输入/输出设备(例如文件、网络连接等)连接起来,使得数据能够在程序和设备之间流动。

Java的IO流分为输入流和输出流两种类型。

  • 输入流用于从外部读取数据
  • 输出流用于向外部写入数据。

Java中的流操作按照字节或字符的方式进行。字节流(byte stream)是以字节为单位进行数据传输的,适用于处理二进制数据。字符流(character stream)是以字符为单位进行数据传输的,适用于处理文本数据。

【Java|基础篇】File类和IO流_第1张图片

这里的InputStream,OutputStream,Reader和Writer都是抽象类.Java提供了一些实现这些抽象父类的子类,用于应对不同的场景.

3.InputStream

InputStream的子类可以根据不同的数据源提供不同的实现,例如FileInputStream用于从文件中读取数据,ByteArrayInputStream用于从字节数组中读取数据,SocketInputStream用于从网络连接中读取数据等。

对于InputStream,主要讲解FileInputStream

    public static void main(String[] args) throws FileNotFoundException {
        InputStream inputStream = new FileInputStream("文件路径");
       
        inputStream.close();
    }

在创建实例时,要传入一个文件路径.这里需要处理一个异常FileNotFoundException(文件没找到).

读文件需要先打开文件,打开才能读,读完之后要关闭文件(close)

InputStream类的常用方法为read()和close()方法

close()方法:关闭输入流,释放与之关联的资源。

而read()方法有三个版本:

【Java|基础篇】File类和IO流_第2张图片

  1. int read():从输入流中读取数据的下一个字节,并返回读取到的字节值。如果已经到达流的末尾,则返回-1。
  2. int read(byte[] b):从输入流中最多读取b.length个字节,并将其存储在字节数组b中。返回实际读取的字节数量。如果已经到达流的末尾,则返回-1
  3. int read(byte b[], int off, int len): 从输入流中读取最多len个字节,并将其存储在从偏移量off开始的字节数组b中。

4.OutputStream

OutputStream的子类可以根据不同的目的地提供不同的实现,例如FileOutputStream用于向文件中写入数据,ByteArrayOutputStream用于向字节数组中写入数据,SocketOutputStream用于向网络连接中写入数据等。

对于OutputStream,主要讲解FileOutputStream

    public static void main(String[] args) throws IOException {
        OutputStream outputStream = new FileOutputStream("文件路径");

        outputStream.close();
    }

close()方法: 关闭输出流,释放资源.

OutputStream中的一个常用方法: write():

【Java|基础篇】File类和IO流_第3张图片

这里有三个重载的版本

  1. write(int b):写入一个字节到输出流中。b是一个整数,表示要写入的字节的值(范围是0~255)。
  2. write(byte[] b):将整个字节数组b写入输出流中。
  3. write(byte[] b, int off, int len):将字节数组b中从偏移量off开始的len个字节写入输出流中。

注意:使用OutputStream写文件时,只要文件打开成功,就会把文件原有的内容清空.

5.Reader

Reader的子类可以根据不同的字符输入源提供不同的实现,例如FileReader用于从文件中读取字符数据,StringReader用于从字符串中读取字符数据,BufferedReader用于从字符缓冲区中读取字符数据等。

使用方式于InputStream类似,只不过Reader是以字符流的形式进行读文件

public static void main(String[] args) throws IOException {
     Reader reader = new FileReader("");
     reader.close();
}

【Java|基础篇】File类和IO流_第4张图片

  1. read():读取单个字符,并返回其Unicode值。如果已到达流的末尾,则返回-1。
  2. read(char[] cbuf):将字符读入到指定的字符数组cbuf中,并返回读取的字符数。
  3. read(char[] cbuf, int off, int len):将字符读入到指定的字符数组cbuf中,从偏移量off开始,最多读取len个字符,并返回实际读取的字符数。
  4. read(CharBuffer target):将字符读入到指定的CharBuffer对象中,并返回读取的字符数。

6.Writer

Writer是用于向字符输出流中写入字符数据。

Writer的子类可以根据不同的字符输出目的地提供不同的实现,例如FileWriter用于向文件中写入字符数据,StringWriter用于向字符串中写入字符数据,BufferedWriter用于向字符缓冲区中写入字符数据等。

【Java|基础篇】File类和IO流_第5张图片

  1. write(int c):将指定的字符写入输出流中。
  2. write(String str):将字符串写入输出流中。
  3. write(char[] cbuf):将字符数组中的字符写入输出流中。
  4. write(String str, int off, int len):将字符串中从偏移量off开始的len个字符写入输出流中。
  5. write(char[] cbuf, int off, int len):将字符数组中从偏移量off开始的len个字符写入输出流中。

7.使用Scanner进行读文件

追对于文本文件,也可以使用Scanner进行读取

例如这里有一个test.txt文件
【Java|基础篇】File类和IO流_第6张图片

接下来介绍使用Scanner进行读文件

public class Demo5 {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("test.txt");

        Scanner scanner = new Scanner(inputStream);
        while (scanner.hasNext()){
            System.out.println(scanner.next());
        }
        inputStream.close();
    }
}

运行结果:

【Java|基础篇】File类和IO流_第7张图片
解释一下:InputStream是字节流,Scanner是在InputStream的基础上,包装出来的字符流.

8.使用PrintWriter写文件

与Scanner进行读文件类似,通过将FileOutputStream对象作为参数,创建了一个PrintWriter对象printWriter。

PrintWriter类提供了一系列的print和println方法,用于以友好的方式输出数据。这些方法可以接受不同类型的数据作为参数,并将其转换为字符串并写入输出流中。

例如,常用的方法包括:

  1. print(boolean b) / println(boolean b):以字符串形式写入一个boolean值。
  2. print(char c) / println(char c):以字符串形式写入一个字符。
  3. print(int i) / println(int i):以字符串形式写入一个整数。
  4. print(double d) / println(double d):以字符串形式写入一个双精度浮点数。
  5. print(String s) / println(String s):写入一个字符串。
  6. printf(String format, Object… args):使用指定的格式字符串和参数进行格式化输出。

需要注意的是,在使用完PrintWriter后,需要调用close()方法关闭流,以确保数据被正确地写入目的地并释放资源。

代码:

public class Demo6 {

    public static void main(String[] args) throws IOException {
        OutputStream outputStream = new FileOutputStream("test.txt");
        PrintWriter printWriter = new PrintWriter(outputStream);
        printWriter.printf("hello PrintWriter");
        printWriter.close();
        outputStream.close();
    }
}

运行结果:
【Java|基础篇】File类和IO流_第8张图片

9.close()方法

上述输入流和输出流的读文件和写文件后,都要进行close.是为什么呢?

原因是 每个进程都对应者PCB(可能是多个),PCB里有一个字段,文件描述符表(同一个进程里有多个PCB共同使用同一份文件描述符表),进程没打开一个文件,就会在文件描述表中创建一个项表示 一个文件.关闭文件意味着释放文件描述表中的项.如果不关闭文件,表项就在这里占着位置. 如果持续打开文件,不关闭,文件描述符表中的项就会被耗尽,从而导致后续打开文件失败. 这也称"文件资源泄漏"

为了避免上述问题,就需要保证close方法一定能被执行到.

因此就可以使用 try,finally保证close方法一定被执行到

    public static void main(String[] args) throws IOException {
        Writer writer = null;
        try {
            writer = new FileWriter("文件路径");
            
            // do something
        } finally {
            writer.close();
        }
        
    }

除了上述这种写法,还有一种写法(try with resources)

    public static void main(String[] args) throws IOException {
        try(Writer writer = new FileWriter("文件路径")) {

            // do something
        }
    }

当try中的代码执行结束,就会自动调用对应对象的close方法.而且()中可以放多个对象,对象之间用;进行分割

10.flush()方法

flush()方法是Java IO流中的一个方法,用于刷新缓冲区,并确保数据被写入到目的地。

缓冲区(Buffer)是用于临时存储数据的一块内存区域,它可以提高IO操作的效率。
在Java的IO流中,使用缓冲区可以减少单次IO操作的次数,从而提高读取和写入数据的效率。通常情况下,IO流会使用内部的缓冲区来存储数据,然后在一定条件下将缓冲区中的数据进行读取或写入。

在Java的输出流(OutputStream/Writer)中,flush()方法的作用是将缓冲区中的数据强制刷新到目的地。通常情况下,输出流会使用内部的缓冲区来提高写入效率,即将数据先写入到缓冲区中,然后再一次性写入到目的地。而flush()方法的调用可以让输出流立即将缓冲区的数据写入到目的地,而不是等到缓冲区满或流关闭时才写入。

注: 调用close()方法也会刷新缓冲区,并确保所有数据都被写入

10.总结

Java IO流主要涉及以下类:

  • InputStream和OutputStream:字节流的基类,用于读取和写入字节数据。
  • Reader和Writer:字符流的基类,用于读取和写入字符数据。
  • FileInputStream和FileOutputStream:用于从文件中读取和写入字节数据。
  • FileReader和FileWriter:用于从文件中读取和写入字符数据。

同时可以使用Scanner和PrintWriter简化开发,使用完流对象后,一定要记得调用close操作.

【Java|基础篇】File类和IO流_第9张图片

你可能感兴趣的:(从零开始的Java学习之旅,#,JavaSE,java,python,开发语言)