File类的用法

目录

File的常见方法

 普通文件的创建

 普通文件的删除

deleteOnExit

目录的创建 

mkdir

mkdirs

文件的重命名和剪切

剪切

 重命名

InputStream

read()

OutputStream

write()

Reader

Writer

write(String str)

代码练习

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

进⾏普通⽂件的复制

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


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

什么是文件(File)?

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

什么是目录(Directory)?

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

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

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

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的常见方法

返回值方法名说明
StringgetParent()返回 File 对象的⽗⽬录⽂件路径
StringgetName()返回文件或目录的最后一个名称
StringgetPath()返回 File 对象的⽂件路径
StringgetAbsolutePath()返回 File 对象的绝对路径
StringgetCanonicalPath()返回文件的规范绝对路径
booleanexists()判断 File 对象描述的⽂件是否存在
booleanisDirectory()判断 File 对象代表的⽂件是否是⼀个⽬录
booleanisFile()判断 File 对象代表的⽂件是否是⼀个普通⽂件
booleancreateNewFile()根据 File 对象,⾃动创建⼀个空⽂件,成功创建后返回 true
booleandelete()根据 File 对象,删除该⽂件。成功 删除后返回 true
voiddeleteOnExit()

根据 File 对象,标注⽂件将被删除,

删除动作会到 JVM 运⾏结束时才会进⾏

String[]list()返回目录中的每个文件和目录的名称(不包括路径)
File[]listFiles()返回目录中所有文件和子目录的File对象(包括路径)
booleanmkdir()创建单个目录,父目录必须存在
booleanmkdirs()

创建多级目录,父目录不存在则会自动创建父目录

booleanrenameTo(File dest)进⾏⽂件改名,也可以视为我们平时的剪切、粘贴操作
booleancanRead()判断⽤⼾是否对⽂件有可读权限
booleancanWrite()判断⽤⼾是否对⽂件有可写权限

 普通文件的创建

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,如果改成其他名字就可以创建成功


    }

 普通文件的删除

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

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

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

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来说如果父目录,也就是中间目录不存在的话则会自动创建父目录,而后者不会

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这个目录
    }

文件的重命名和剪切

剪切

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

 

 重命名

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

返回值方法名作用
intread()读取⼀个字节的数据,返回 -1 代表 已经完全读完了
intread(byte[] b)

最多读取 b.length 字节的数据到 b 中,返回实际读到的数量

;-1 代表 以及读完了

intread(byte[] b, int off, int len)

最多读取 len - off 字节的数据到 b 中,放在从 off 开始,

返回实际读 到的数量;-1 代表以及读完了

voidclose()关闭字节流

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

read()

代码1

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 

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 来读取中文

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

返回值方法名说明
voidwrite(int b)写⼊要给字节的数据,一次只能写入一个字节
voidwrite(byte[] b)

将 b 这个字符数组中的数据全部写 ⼊ os 中

一次可以写入多个字节

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

write()

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

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” 参数

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

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

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

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)icon-default.png?t=N7T8http://www.mytju.com/classCode/tools/encode_utf8.asp

Writer

write(String str)

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

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

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

代码练习

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

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);
    }
}

进⾏普通⽂件的复制

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

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这个父目录必须存在,这段代码不仅可以复制文件还可以复制图片等

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

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());
    }

}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值