文件操作File类,OutputStream、InputStream、Reader、Writer的用法

文章目录

  • File 类
  • OutputStream、InputStream
    • InputStream
    • OutputStream
  • Reader、Writer
    • Reader
    • Writer
  • 注意事项
  • 简单模拟实战

File 类

Java标准库中提供的File类是对硬盘上的文件的抽象,每一个File对象代表了一个文件,因为文件在硬盘上存储,而直接操作硬盘太过麻烦,所以我们就在内存中抽象一个文件对象,通过改变这个对象间接改变硬盘上的文件。

在构造对象时我们可以使用绝对路径或者相对路径,构造的文件对象可以真实存在也可以不存在,标准库中也为我们提供了很多的方法:

返回值类型 方法名 说明
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(Filedest) 进行文件改名,也可以视为我们平时的剪切、粘贴操作
boolean canRead() 判断用户是否对文件有可读权限
boolean canWrite() 判断用户是否对文件有可写权限

下面我们来简单的示范使用一下:

此时我们创建File对象使用的是相对路径,此时项目所在的目录就是工作目录,我们通过调用一些方法获取到了文件的相关信息。

文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第1张图片

此时我们使用一个不存在的文件去创建File对象,同样可以成功,因为创建File对象是不要求文件一定存在,此时我们通过方法去判断File对象是否是一个文件或者目录,肯定返回的是false,我们可以调用createNewFile()去创建该文件,创建后再次进行判断。

文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第2张图片

使用mkdir()可以创建目录,想要创建多级目录使用mkdirs()

文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第3张图片

list可以返回File对象下的所有文件名,listFiles返回时包含自己,此时根据上图我们创建的多级目录可以看出,test目录下的文件只有一个aa。

文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第4张图片
以上就是Java中File类的简单介绍。

OutputStream、InputStream

我们可以创建文件删除文件之后,是不是要向文件当中写入一些东西,或者从文件中读取一些东西。此时Java也为我们提供很对类:

针对文本文件,可以使用:Reader Writer去读和写,他们读写的基本单位是字符,称为字符流。

针对二进制文件,可以使用InputStream OutputStream,他们读写的基本单位是字节,称为字节流。

我们有了一个新的概念叫做流,这该怎么理解呢?
文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第5张图片

InputStream

返回值类型 项目 Value
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() 关闭字节流

文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第6张图片

此时我们创建一个txt文件,通过InputStream对象去读取这个文件里面的内容:

文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第7张图片

OutputStream

返回值类型 项目 Value
void write(int b) 写入要给字节的数据
void write(byte[]b) 将 b 这个字符数组中的数据全部写入 os 中
int write(byte[]b, int off,int len) 将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个
void close() 关闭字节流
void flush() 重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。

我们通过OutputStream向刚才创建的txt文件中写入一些数据:
文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第8张图片

此时我们发现,文件中的内容从abc变为了我们输入的内容

Reader、Writer

Reader

文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第9张图片

Writer

文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第10张图片
同样使用Writer对象向txt文件中写入一些数据。

注意事项

1、上述的类OutputStream、InputStream都是抽象类,实现的时候需要使用具体的类,他们的实现类有很多,目前我们只关心从文件中读写,所以使用FileInputStream。Reader、Writer也是一样,都是抽象类,实现需要具体的类。

2、每次使用完必须要使用close()进行关闭,在一个进程中,当我们打开一个文件就会有一个文件描述符记录我们打开了哪些文件,这些文件描述符多了之后会生成一个文件描述符表,每次打开会在这个表中申请一个位置,但是这个表的大小是有限制的,如果不进行关闭释放,表满了再打开文件就会失败。

有的兄弟会说了,上述代码你一个close()也没有啊!!!正常来说我们打开文件和关闭文件可以这样写:
文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第11张图片
但是这样会导致如果代码很复杂有可能close()方法执行不到,我们进行优化:
文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第12张图片
这样写可以保证close()方法一定被执行到,但是这样写不够优雅,我们再次优化,Java给我们提供了一个语法叫做try with resources
文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第13张图片
因为InputStream实现了一个特定的接口Closeable,所以带有资源的try操作,会在try代码块结束,自动执行close操作。

简单模拟实战

需求:扫描指定目录,找到包含相关内容的的普通文件

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Scanner;

public class IOTestMyself {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        while (true) {
            System.out.println("请输入你要查找的目录:");
            File rootDir = new File(scanner.next());
            if (!rootDir.isDirectory()) {
                System.out.println("您输入的目录不存在,请重新输入");
            }else {
                System.out.println("请输入你要查找的内容:");
                String word = scanner.next();
                scanDir(rootDir,word);
                break;
            }
        }
    }

    private static void scanDir(File rootDir,String word) {
        File[] files = rootDir.listFiles();
        if(files == null) {
            return;
        }
        for (File f: files) {
            System.out.println("当前查找目录" + f.getAbsolutePath());//打印一下日志
            if(f.isFile()) {
                //是文件就查找
                String ret = readFile(f);
                if(ret.contains(word)) {
                    System.out.println(f.getAbsolutePath() + "包含查找内容");
                }
            }else if(f.isDirectory()) {
                //是目录递归查找下级目录
                scanDir(f,word);
            }else {
                //啥也不是跳过
                continue;
            }
        }
    }

    private static String readFile(File f) {
        StringBuilder stringBuilder = new StringBuilder();
        try (Reader reader = new FileReader(f)){
            while (true) {
                int c = reader.read();
                if(c == -1) {
                    break;
                }
                stringBuilder.append((char)c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return stringBuilder.toString();
    }
}

文件操作File类,OutputStream、InputStream、Reader、Writer的用法_第14张图片

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