Java中的文件操作

1. File类概述

Java中通过 java.io.File 类来对⼀个⽂件(包括⽬录)进⾏抽象的描述。注意,有File对象,
并不代表真实存在该⽂件。

 1.1 属性

Java中的文件操作_第1张图片

在Java中提供了这两个常量来获取对应的系统的文件路径分隔符

pathSeparatorChar是一个字符常量,表示系统相关的路径分隔符。它的值由fs.getPathSeparator()方法返回。
pathSeparator是一个字符串常量,方便使用和操作路径分隔符。它的值是将pathSeparatorChar转换为字符串得到的。

1.2 构造方法

在Java中,File类提供了三个构造函数用于创建文件对象:

  • File(String pathname):根据指定的路径名创建一个新的文件对象。
    参数pathname是要创建的文件的路径名,可以是相对路径或绝对路径。
  • File(File parent, String child):根据指定的父路径和子路径创建一个新的文件对象。
    参数parent是文件对象的父目录。
    参数child是文件对象的子目录或文件名。
  • File(String parent, String child):根据指定的父路径名和子路径名创建一个新的文件对象。
    参数parent是文件对象的父目录的路径名。
    参数child是文件对象的子目录或文件名的路径名。

代码演示:

import java.io.File;
public class IODemo1 {
    public static void main(String[] args) {
        // 通过路径名创建文件对象
        File file1 = new File("C:/Users/22759/Desktop/Ting__JAVA/J20240117-IO/file.txt");//绝对路径
        File file2 = new File("./file.txt");//相对路径
        /*注意:使用相对路径时,如果是在idea中运行程序,此时工作目录为项目所在目录(即 . 代表的目录)
        如果是把代码打包成一个单独的jar包,则工作目录为jar包所在的目录
         */

        // 通过路径名创建文件对象
        File parentDir = new File("C:/Users/22759/Desktop/Ting__JAVA/J20240117-IO");
        File file3 = new File(parentDir, "file.txt");

        // 通过父路径名和子路径名创建文件对象
        File file4 = new File("C:/Users/22759/Desktop/Ting__JAVA/J20240117-IO", "file.txt");
    }
}

1.3 常用方法

返回值类型 方法名 说明
String getParent() 返回 File 对象的父目录文件路径
String getName() 返回 File 对象的纯文件名称
String getPath() 返回 File 对象的文件路径
String getAbsolutePath() 返回 File 对象的绝对路径
String getCanonicalPath() 返回 File 对象的修饰过的绝对路径
boolean exists() 判断 File 对象描述的文件是否真实存在
boolean isDirectory() 判断 File 对象代表的文件是否是一个目录
boolean isFile() 判断 File 对象代表的文件是否是一个普通文件
boolean createNewFile() 根据 File 对象,自动创建一个空文件。成功创建后返回 true
boolean delete() 根据 File 对象,删除该文件。成功删除后返回 true
void deleteOnExit()

根据 File 对象,标注文件将被删除,删除动作

会到 JVM 运行结束时才会进行

String[] list() 返回 File 对象代表的目录下的所有文件名
File[] listFiles() 返回 File 对象代表的目录下的所有文件,以 File 对象表示
boolean mkdir() 创建 File 对象代表的目录
boolean mkdirs() 创建 File 对象代表的目录,如果必要,会创建中间目录
boolean renameTo(File dest) 进行文件改名,也可以视为我们平时的剪切、粘贴操作
boolean canRead() 判断用户是否对文件有可读权限
boolean canWrite() 判断用户是否对文件有可写权限


2. 文件的读写

2.1 数据流

数据流(Data Stream)是指在计算机中,数据在输入和输出设备之间传输的流动方式。数据可以以不同的形式流动,如字节流、字符流等。

字节流(Byte Stream)以字节为单位进行数据传输,适用于处理二进制数据。字节流可以分为输入字节流和输出字节流。常见的字节流类有InputStream和OutputStream。

字符流(Character Stream)以字符为单位进行数据传输,适用于处理文本数据。字符流可以分为输入字符流和输出字符流。常见的字符流类有Reader和Writer。

2.2 字节流

 2.2.1 InputStream

InputStream是抽象类,用于从输入源(如文件、网络连接等)读取数据。以下是使用InputStream的几个常用步骤:

1. 创建InputStream对象:可以使用FileInputStream、ByteArrayInputStream、Socket.getInputStream()等构造方法创建InputStream对象。

public class IODemo3 {
    public static void main(String[] args) throws FileNotFoundException {
        InputStream inputStream = new FileInputStream("./file.txt");//相当于打开文件
    }
}


2. 读取数据:使用read()方法从输入流中读取数据。read()方法。

Java中的文件操作_第2张图片

int read():  返回下一个字节的整数值,如果已经到达流的末尾,则返回-1可以使用循环结构来连续读取数据,直到返回-1为止。

        InputStream inputStream = new FileInputStream("./file.txt");//相当于打开文件
        while(true) {
            int n = inputStream.read();
            if(n == -1) {
                break;
            }
            System.out.print(n + " ");
        }

int read(byte[] b) : 从输入流中读取最多b.length个字节的数据,并将其存储在给定的字节数组b中。该方法返回实际读取的字节数,如果已经到达流的末尾,则返回-1。


        InputStream inputStream = new FileInputStream("./file.txt");//相当于打开文件
        byte[] b = new byte[10];
        int n = inputStream.read(b);
        System.out.println("n == " + n);
        for(int i = 0 ; i < n; i++) {
            System.out.print(b[i] + " ");
        }
    

int read(byte[] b, int off, int len): 从输入流中读取最多len个字节的数据,并将其存储在给定的字节数组b中,存储位置从off索引处开始。该方法返回实际读取的字节数,如果已经到达流的末尾,则返回-1。


        InputStream inputStream = new FileInputStream("./file.txt");//相当于打开文件
        byte[] b = new byte[10];
        int n = inputStream.read(b, 0, 4);
        System.out.println("n == " + n);
        for(int i = 0 ; i < n; i++) {
            System.out.print(b[i] + " ");
        }
   


3. 关闭InputStream:使用close()方法关闭输入流,释放资源。

public class IODemo3 {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("./file.txt");//相当于打开文件
        while(true) {
            int n = inputStream.read();
            if(n == -1) {
                break;
            }
            System.out.print(n + " ");
        }
        inputStream.close();//释放资源
    }
}

注意:在实际开发中可能由于各种原因,上述写法中的close可能无法执行到,比如抛出异常了,或者提前返回了,所有我们可以对上述代码做出一些改进:

public class IODemo4 {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = null;//相当于打开文件
        try {
            inputStream = new FileInputStream("./file.txt");
            while(true) {
                int n = inputStream.read();
                if(n == -1) {
                    break;
                }
                System.out.print(n + " ");
            }
        }finally {
            inputStream.close();//释放资源
        }
    }
}

我们使用try-catch将close放在finally中,保证close一定会被执行

我们也可以使用try-catch的另一版本 try with resource:

public class IODemo4 {
    public static void main(String[] args) throws IOException {
        try(InputStream inputStream = new FileInputStream("./file.txt")) {
            while(true) {
                int n = inputStream.read();
                if(n == -1) {
                    break;
                }
                System.out.print(n + " ");
            }
        }
    }
}

在代码执行出try的代码块时,try会自动调用close方法

注意:只用实现了Closeable接口的类才会自动调用close方法

2.2.2 OutPutStream

OutputStream也是一个抽象类,它是所有输出流类的基类。
使用方法与InPutStream大致相同:

Java中的文件操作_第3张图片

OutPutStream提供了三个write方法:

void write(int b) :这个方法将指定字节写入输出流。被写入的数据是参数b的低八位。

public class IODemo5 {
    public static void main(String[] args) throws IOException {
        try(OutputStream outputStream = new FileOutputStream("./file.txt")) {
            outputStream.write(97);//写入一个a
        }
    }
}

void write(byte[] b) :这个方法将参数字节数组b中的所有字节写入输出流。

public class IODemo5 {
    public static void main(String[] args) throws IOException {
        try(OutputStream outputStream = new FileOutputStream("./file.txt")) {
            byte[] b = {97, 98, 99};
            outputStream.write(b); //写入b数组中的所有数据
        }
    }
}

void write(byte[] b, int off, int len) :这个方法将从参数字节数组b中的偏移量off开始写入len个字节到输出流。

public class IODemo5 {
    public static void main(String[] args) throws IOException {
        try(OutputStream outputStream = new FileOutputStream("./file.txt")) {
            byte[] b = {97, 98, 99};
            outputStream.write(b, 0, 3);//从b数组的0号下标开始写入3个数据
        }
    }
}

我们发现每次写入数据时文件中的内容都会被清空再重新写入,要想不清空直接在后面续写,我们只需要在实例化OutPutStream时在后面加上一个参数true即可:

public class IODemo5 {
    public static void main(String[] args) throws IOException {
        try(OutputStream outputStream = new FileOutputStream("./file.txt", true)) {
            byte[] b = {97, 98, 99};
            outputStream.write(97);//写入一个a
            outputStream.write(b);
            outputStream.write(b, 0, 3);
        }
    }
}

void flush() 方法:写数据时会先把数据写入缓冲区,等数据超过某个阈值时才会写入目标文件,这个方法会将输出流的缓冲区内容强制刷新到输出目标中(如文件、网络连接等),以确保所有缓冲数据都被写入目标。

2.3 字符流

2.3.1 Reader

Reader也是一个抽象类,不能直接实例化

使用方法类比InPutStream,只不过从按字节为单位变成了按字符为单位

Reader也是通过read方法读取:

Java中的文件操作_第4张图片

int read():从输入流中读取下一个字符的数据,并将其作为整数返回。如果已经到达流的末尾,即没有更多的数据可读取,则返回-1。

int read(char[] cbuf):从输入流中读取最多cbuf.length个字符的数据,并将其存储在给定的字符数组cbuf中。该方法返回实际读取的字符数,如果已经到达流的末尾,则返回-1

int read(CharBuffer target):从输入流中读取字符,并将其存储到提供的CharBuffer对象中。它返回实际读取的字符数,如果已经到达流的末尾,则返回-1。

int read(char[] cbuf, int off, int len):从输入流中读取最多len个字符的数据,并将其存储在给定的字符数组cbuf中,存储位置从off索引处开始。该方法返回实际读取的字符数,如果已经到达流的末尾,则返回-1。

public class IODemo {
    public static void main(String[] args) throws IOException {
        try(Reader reader = new FileReader("./file.txt")) {
            char[] b = new char[100];
            int n = reader.read(b);
            System.out.println(new String(b, 0, n));
        }
    }
}

Java中的文件操作_第5张图片

运行程序就可以输出file.txt 中的内容。

但此处有一个细节:在Java中 char类型占2个字节,而utf8编码的中文占3个字节,b数组是如何存储中文的?

我们换一种打印方式:

public class IODemo {
    public static void main(String[] args) throws IOException {
        try(Reader reader = new FileReader("./file.txt")) {
            char[] b = new char[100];
            int n = reader.read(b);
            //System.out.println(new String(b, 0, n));
            for(int i = 0; i < n; i++) {
                System.out.print(b[i] + " ");
            }
        }
    }
}

Java中的文件操作_第6张图片

这是因为字符在被读到字符数组时,是先被转化为Unicode编码,构造成字符串时再被转化为utf8编码 

2.3.2 Writer

Writer是Java IO包中的一个抽象类,它是所有字符输出流的超类。它提供了一系列方法,用于将字符数据从内存写入到输出流中。

Writer类的常用方法包括:

write(int c):将指定的字符写入输出流。
write(char[] cbuf):将字符数组中的数据写入输出流。
write(String str):将字符串写入输出流。
write(char[] cbuf, int off, int len):将字符数组中的一部分数据写入输出流。
flush():刷新输出流,确保所有待输出的数据都被写入到输出流中。
close():关闭输出流。

使用方法类比OutPutStream

public class IODemo6 {
    public static void main(String[] args) throws IOException {
        try(Writer writer = new FileWriter("./file.txt")) {
            writer.write("你好Java");
        }
    }
}

你可能感兴趣的:(java,开发语言)