File类的用法

目录

File的常见方法

普通文件的创建

普通文件的删除

deleteOnExit

目录的创建

mkdir

mkdirs

文件的重命名和剪切

剪切

重命名

InputStream

read()

OutputStream

write()

Reader

Writer

[write(String str)](#write(String str))

代码练习

[扫描指定⽬录,并找到名称中包含指定字符的所有普通⽂件(不包含⽬录),并且后续询问⽤⼾是否 要删除该⽂件](#扫描指定⽬录,并找到名称中包含指定字符的所有普通⽂件(不包含⽬录),并且后续询问⽤⼾是否 要删除该⽂件)

进⾏普通⽂件的复制

扫描指定⽬录,并找到名称或者内容中包含指定字符的所有普通⽂件(不包含⽬录)


File是Java中的一个重要类,位于java.io包中,可以用来创建、删除、查询文件或目录等

什么是文件(File)?

文件可以是文本、图像、视频、音频、程序代码等多种类型的数据

什么是目录(Directory)?

通俗点来说,目录就是文件夹,用于将多个文件存放在一起,便于管理

什么是绝对路径,什么是相对路径,什么是工作路径?

绝对路径就是从根目录开始的,绝对路径不受当前工作路径的影响,而相对路径就是从当前目录开始,System.getProperty("user.dir") 这种方式来获取当前的工作路径

java 复制代码
public static void main(String[] args) throws IOException {
        File file = new File("test1.txt");
        System.out.println(file.getName());//文件或目录最后一个路径元素
        System.out.println(file.getPath());//返回文件的路径
        System.out.println(file.getAbsoluteFile());//返回文件的绝对路径
        System.out.println(file.getCanonicalFile());//返回文件规范的绝对路径
    }

运行结果:

File的常见方法

|------------|---------------------|-------------------------------------------|
| 返回值 | 方法名 | 说明 |
| String | getParent() | 返回 File 对象的⽗⽬录⽂件路径 |
| String | getName() | 返回文件或目录的最后一个名称 |
| String | getPath() | 返回 File 对象的⽂件路径 |
| String | getAbsolutePath() | 返回 File 对象的绝对路径 |
| String | getCanonicalPath() | 返回文件的规范绝对路径 |
| boolean | exists() | 判断 File 对象描述的⽂件是否存在 |
| boolean | isDirectory() | 判断 File 对象代表的⽂件是否是⼀个⽬录 |
| boolean | isFile() | 判断 File 对象代表的⽂件是否是⼀个普通⽂件 |
| boolean | createNewFile() | 根据 File 对象,⾃动创建⼀个空⽂件,成功创建后返回 true |
| boolean | delete() | 根据 File 对象,删除该⽂件。成功 删除后返回 true |
| void | deleteOnExit() | 根据 File 对象,标注⽂件将被删除, 删除动作会到 JVM 运⾏结束时才会进⾏ |
| String[] | list() | 返回目录中的每个文件和目录的名称(不包括路径) |
| File[] | listFiles() | 返回目录中所有文件和子目录的File对象(包括路径) |
| boolean | mkdir() | 创建单个目录,父目录必须存在 |
| boolean | mkdirs() | 创建多级目录,父目录不存在则会自动创建父目录 |
| boolean | renameTo(File dest) | 进⾏⽂件改名,也可以视为我们平时的剪切、粘贴操作 |
| boolean | canRead() | 判断⽤⼾是否对⽂件有可读权限 |
| boolean | canWrite() | 判断⽤⼾是否对⽂件有可写权限 |

普通文件的创建

java 复制代码
public static void main(String[] args) throws IOException {
        File file = new File("D:\\java");
        System.out.println(file.exists());//true
        System.out.println(file.isDirectory());//true,因为'java'为目录
        System.out.println(file.isFile());//false
        System.out.println(file.createNewFile());//false,因为'java'是个文件夹如果
        //再次创建的话会返回false,如果改成其他名字就可以创建成功


    }

普通文件的删除

java 复制代码
public static void main(String[] args) throws IOException {
        File file = new File("D:\\java\\test1.txt");
        System.out.println(file.exists());//返回false,因为test1.txt并没有在'java'这个路径上
        System.out.println(file.createNewFile());//返回true,并成功创建出test1.txt这个文本文件
        System.out.println(file.exists());//返回true,因为成功创建出了test1.txt,所以可以找到
        System.out.println(file.delete());//返回true,因为存在所以可以删除,如果不存在则删除失败返回false
        System.out.println(file.exists());//返回false,因为成功删除,所以在当前路径下找不到test1.txt
    }

deleteOnExit

我们可以将这个理解成延迟删除,意思是只有当程序运行结束的时候才会删除

java 复制代码
public static void main(String[] args) {
        File file = new File("D:\\java\\test.txt");
        file.deleteOnExit();
        Scanner scanner = new Scanner(System.in);
        System.out.println("请随便输入");
        scanner.next();//输入,用来观察是否被删除
        System.out.println("删除成功");
    }

通过下面这张图可以观察到当程序还未结束的时候,这个文件是没有被删除的,但是当我输入完并按下回车之后,这个文件就会立刻被删掉

目录的创建

mkdir

java 复制代码
public static void main(String[] args) {
        File file = new File("D:\\java\\newFile1");
        System.out.println(file.isDirectory());//用来判断是否为目录,如果是返回true,如果不是返回false
        System.out.println(file.mkdir());//创建成功,因为'java'这个目录存在
        //如果'java'这个目录不存在则创建失败,那么就使用mkdirs
    }

mkdirs

mkdirs与mkdir不同的是,对于mkdirs来说如果父目录,也就是中间目录不存在的话则会自动创建父目录,而后者不会

java 复制代码
public static void main(String[] args) {
        File file = new File("D:\\java\\newFile2\\newFile3");
        System.out.println(file.mkdirs());//在'java'这个目录下创建一个newFile2目录
        //并在newFile2这个目录下创建newFile3,因为newFile2这个目录不存在,但是我们使用的是
        //mkdirs所以会自动帮我们创建好newFile2这个目录
    }

文件的重命名和剪切

剪切

java 复制代码
public static void main(String[] args) {
        File src = new File("D:\\java\\test1.txt");
        File dest = new File("D:\\java\\File1\\test2.txt");
        System.out.println(src.exists());
        System.out.println(dest.exists());
        System.out.println(src.renameTo(dest));
    }

没执行前

java文件中保存着test1.txt 和 test2.txt 这两个文本文件,并且File1 目录里面为空

程序执行后

将D:\java\test1.txt 移动到 D:\java\File1\ 目录并重命名为 test2.txt

重命名

java 复制代码
public static void main(String[] args) {
        File src = new File("D:\\java\\test1.txt");
        File dest = new File("D:\\java\\test3.txt");
        System.out.println(src.exists());
        System.out.println(dest.exists());//要求test3不存在
        System.out.println(src.renameTo(dest));
    }

运行结果

只有当目标文件不存在的时候才能完成重命名操作,所以上述代码成功将 test1.txt 重命名为 test3.txt

InputStream

|------|------------------------------------|-------------------------------------------------------------|
| 返回值 | 方法名 | 作用 |
| int | read() | 读取⼀个字节的数据,返回 -1 代表 已经完全读完了 |
| int | read(byte[] b) | 最多读取 b.length 字节的数据到 b 中,返回实际读到的数量 ;-1 代表 以及读完了 |
| int | read(byte[] b, int off, int len) | 最多读取 len - off 字节的数据到 b 中,放在从 off 开始, 返回实际读 到的数量;-1 代表以及读完了 |
| void | close() | 关闭字节流 |

InputStream 只是⼀个抽象类,要使⽤还需要具体的实现类。

read()

代码1

java 复制代码
public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("D:\\java\\test.txt");
        while(true){
            int b = inputStream.read();
            if(b == -1){
                break;
            }
            System.out.printf("%c",b);
        }
        inputStream.close();
    }

代码2

java 复制代码
public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("D:\\java\\test.txt");
        while(true){
            byte[] buffer = new byte[1024];
            int len = inputStream.read(buffer);
            if(len == -1) break;
            for(int i = 0;i<len;i++){
                System.out.printf("%c",buffer[i]);
            }
        }
    }

代码2相对于代码1来说减少了大量的 IO 操作,因为 read() 方法是一次读一个字节,而代码2就是利用这一点将读取到的数据放到 buffer 里面,直到读满1024个字节或者内容读取完毕才会执行打印,这样就减少了大量的 IO 操作

运行结果就是看你的 test.txt 里面的内容是什么,但是不推荐内容包含中文,如果需要使用

复制代码
FileInputStream 来查看有包含中文内容的请继续往下看

使用 FileInputStream 来读取中文

java 复制代码
public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("D:\\java\\test.txt");
        byte[] buffer = new byte[1024];
        while(true){
            int len = inputStream.read(buffer);
            if(len == -1) break;
            for(int i = 0;i<len;i+=3){
                String s = new String(buffer,i,3,"UTF-8");
                System.out.printf("%s",s);
            }
        }
        inputStream.close();
    }

但是这样写就会有一个弊端,就是文本中必须全部都是中文,因为对于UTF8来说,每个汉字都会被分割成3个字节

OutputStream

|------|-------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 返回值 | 方法名 | 说明 |
| void | write(int b) | 写⼊要给字节的数据,一次只能写入一个字节 |
| void | write(byte[] b) | 将 b 这个字符数组中的数据全部写 ⼊ os 中 一次可以写入多个字节 |
| int | write(byte[] b, int off, int len) | 读取 b 这个字符数组从 [off,off+len) 的长度 |
| void | close() | 关闭字节流 |
| void | flush() | 我们知道 I/O 的速度是很慢 的,所以,⼤多的 OutputStream 为了减少设备操作的次数,在写数 据的时候都会将数据先暂时写⼊内 存的⼀个指定区域⾥,直到该区域 满了或者其他指定条件时才真正将 数据写⼊设备中,这个区域⼀般称 为缓冲区。但造成⼀个结果,就是 我们写的数据,很可能会遗留⼀部 分在缓冲区中。需要在最后或者合 适的位置,调⽤ flush(刷新)操 作,将数据刷到设备中。 |

write()

在代码中,如果我们使用**try-with-resources****语句,**则不用手动进行字符/字节流的关闭,因为如果在try代码块结束的时候就会自动调用 close ,而不需要手动进行,用来放在忘记关闭而导致的内存泄漏问题

java 复制代码
public static void main(String[] args) {
        try(OutputStream os = new FileOutputStream("D:\\test.txt")){
            os.write('H');
            os.write('E');
            os.write('L');
            os.write('L');
            os.write('O');
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

但是使用上述代码我们可以看到,如果我们再进行一次写操作,之前的内容就会消失不见,这是因为只要我们使用OutputStream 打开文件,里面的内容就会消失,如何解决这个问题也很简单,因为OutputStream 默认是会清空之前的内容的,但是我们还有一个追加操作,就是在路径后面写一个" true" 参数

java 复制代码
OutputStream os = new FileOutputStream("D:\\java\\test.txt",true)

我们也可以用 write(byte[] b)方法进行写入,方式如下

java 复制代码
public static void main(String[] args) {
        try(OutputStream os = new FileOutputStream("D:\\java\\test.txt",true)){
            byte[] b = new byte[]{'a','b','c','d'};
            os.write(b);
        } catch (IOException e){
            e.printStackTrace();
        }
    }

但是当我们使用InputStream 和 OutputStream 的时候读取和写入中文就比较麻烦,所以我们可以使用更简单的方法来进行中文的输入和输出,请看下文


Reader

java 复制代码
public static void main(String[] args) {
        try(Reader reader = new FileReader("D:\\java\\test.txt")){
            while(true){
                int n = reader.read();
                if(n == -1){
                    return;
                }
                char ch = (char)n;
                System.out.print(ch+" ");
            }
        } catch (IOException e){
            e.printStackTrace();
        }
    }

对于这段代码来说,不管你的内容是中文还是英文还是中英混杂都可以正确的读取出来

输出结果:

看到这里可能就会有一个疑问?明明 java 中的 char 类型表示的是 2 个字节,但是 java 中的汉字是使用 utf8 来表示的,一个汉字 3 个字节,为什么可以使用 char 来表示 3个字节的汉字呢?其实

java 的 char 在表示汉字的时候并不是用 utf8 而是使用 unicode 的编码方式,在 unicode 中一个汉字就表示 2 个字节

在这里我也推荐一个很好用的查看字符编码的网站

查看字符编码(UTF-8)http://www.mytju.com/classCode/tools/encode_utf8.asp

Writer

write(String str)

这个方法可以直接写入字符串,非常方便,如果要进行追加操作也一样在后面加个true就可以

java 复制代码
public static void main(String[] args) {
        try(Writer writer = new FileWriter("D:\\java\\test.txt",true)){
            writer.write("你好中国");
        } catch (IOException e){
            e.printStackTrace();
        }
    }

其他方法其实和前面介绍的都差不多,这里就不再重复了

代码练习

扫描指定⽬录,并找到名称中包含指定字符的所有普通⽂件(不包含⽬录),并且后续询问⽤⼾是否 要删除该⽂件

java 复制代码
package FileTest;

import java.io.File;
import java.util.Scanner;

public class demo15 {

    private static void scan(File currentFile,String key){
        if(!currentFile.isDirectory()){
            return;
        }
        File[] files = currentFile.listFiles();
        if(files.length == 0 || files == null){
            return;
        }
        for(File f : files){
            if(f.isFile()){
                FileDelete(f,key);
            } else {
                scan(f,key);
            }
        }
    }

    private static void FileDelete(File f,String key){
        if(!f.getName().contains(key)){
            //文件名中不包含指定的关键字
            return;
        }
        Scanner scanner = new Scanner(System.in);
        System.out.println(f.getAbsoluteFile()+"是否要删除Y/y");
        String choice = scanner.next();
        if(choice.equals("y") || choice.equals("Y")){
            f.delete();
        }
    }

    public static void main(String[] args) {
        System.out.println("请输入要搜索的路径");
        Scanner scanner = new Scanner(System.in);
        String rootPath = scanner.next();
        File rootFile = new File(rootPath);
        if(!rootFile.isDirectory()){
            System.out.println("输入的路径不存在");
            return;
        }
        //走到此处就说明路径存在
        System.out.println("请输入要删除的文件名字的关键字");
        String key = scanner.next();

        //利用递归进行查找
        scan(rootFile,key);
    }
}

进⾏普通⽂件的复制

如果文件在目录中不存在,就会自动创建,但是如果连目录都不存在那就不行了

java 复制代码
package FileTest;

import java.io.*;
import java.util.Scanner;

public class demo17 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入源文件的路径");
        String srcPath = scanner.next();
        File srcFile = new File(srcPath);
        if(!srcFile.isFile()){
            System.out.println("源文件路径有误");
            return;
        }

        System.out.println("请输入目标文件的路径");
        String destPath = scanner.next();
        File destFile = new File(destPath);
        //注意: 这里目标文件可以不存在但是父目录必须存在
        if(!destFile.getParentFile().isDirectory()){
            System.out.println("目标文件路径有误");
            return;
        }

        //执行复制的过程
        try(InputStream inputStream = new FileInputStream(srcFile);
            OutputStream outputStream = new FileOutputStream(destFile)){

            while(true){
                byte[] buffer = new byte[1024];
                int n = inputStream.read(buffer);//返回读到的字节数量
                if(n == -1){
                    return;
                }
                outputStream.write(buffer,0,n);//读取0~n个,因为buffer可能装不满
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

代码执行前:

代码执行后:

执行过程:

D:\java\test.txt 的意思就是将 test.txt 复制到D:\java\File1 这个路径里面并重命名为 newtest.txt

这里的File1这个父目录必须存在,这段代码不仅可以复制文件还可以复制图片等

扫描指定⽬录,并找到名称或者内容中包含指定字符的所有普通⽂件(不包含⽬录)

java 复制代码
package FileTest;

import java.io.*;
import java.util.Scanner;

public class demo18 {
    public static void main(String[] args) {
        System.out.println("请输入要搜索的路径");
        Scanner scanner = new Scanner(System.in);
        String rootPath = scanner.next();
        File rootFile = new File(rootPath);
        if(!rootFile.isDirectory()){
            System.out.println("路径不存在");
            return;
        }
        System.out.println("请输入要找的关键字");
        String key = scanner.next();
        scan(rootFile,key);

    }

    private static void scan(File rootFile, String key) {
        if(!rootFile.isDirectory()){
            return;
        }
        File[] files = rootFile.listFiles();
        if(files.length == 0 || files == null){
            return;
        }
        for(File f : files){
            if(f.isFile()){
                search(f,key);
            } else {
                scan(f,key);
            }
        }
    }

    private static void search(File f, String key) {
        StringBuilder sb = new StringBuilder();
        try(Reader reader = new FileReader(f)){
            char[] buffer = new char[1024];
            while(true){
                int n = reader.read(buffer);
                if(n == -1){
                    break;
                }
                String s = new String(buffer,0,n);//将每个字符拼接成字符串
                sb.append(s);//将读到的字符串拼接到一起最后判断
            }
        } catch (IOException e){
            e.printStackTrace();
        }

        if(sb.indexOf(key) == -1){
            //没有找到
            return;
        }
        System.out.println("找到匹配的文件: "+f.getAbsolutePath());
    }

}

上述代码只要文件中包含了关键字的都能被找的,但是这个并不能适用太复杂的目录或者文件太大的情况

相关推荐
晴子呀11 分钟前
Spring底层原理大致脉络
java·后端·spring
只吹45°风18 分钟前
Java-ArrayList和LinkedList区别
java·arraylist·linkedlist·区别
阿华的代码王国25 分钟前
【JavaEE】多线程编程引入——认识Thread类
java·开发语言·数据结构·mysql·java-ee
黑蛋同志26 分钟前
array和linked list的区别
java
andrew_121932 分钟前
腾讯 IEG 游戏前沿技术 一面复盘
java·redis·sql·面试
寻求出路的程序媛40 分钟前
JVM —— 类加载器的分类,双亲委派机制
java·jvm·面试
这孩子叫逆41 分钟前
35. MyBatis中的缓存失效机制是如何工作的?
java·spring·mybatis
骆晨学长42 分钟前
基于SpringBoot的校园失物招领系统
java·spring boot
汇匠源42 分钟前
零工市场小程序:保障灵活就业
java·小程序·零工市场
计算机编程-吉哥1 小时前
计算机毕业设计 二手图书交易系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试
java·spring boot·毕业设计·毕业论文·计算机毕业设计选题·计算机毕业设计开题报告·二手图书交易系统