File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法

文章目录

  • 文件内容的读写
  • File类
  • stream
    • InputStream
      • 使用字节流读文件
      • 使用Scanner读文件
    • OutputStream
      • 使用字节流写文件
      • 使用PrintWriter进行写操作
    • Reader
      • 使用字符流读文件
    • Wirter
      • 使用字符流写文件
  • close()
  • 总结


文件内容的读写

文件操作,是属于操作系统层面提供的一些API.
不同的操作系统,提供的API是不一样的~
Java作为一个跨平台的语言,为了统一代码,就在JVM中把不同系统的操作文件的的API进行了封装~ Java 就可以使用Java中的库的代码来操作文件了~~
Java 中通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述。

注意:有 File 对象,并不代表真实存在该文件

IO:

  • I :input 输入
  • O output 输出 输入输出的方向,就是以CPU/内存为中心 ~

在这里插入图片描述

File类

File类的属性:

修饰符及类型 属性 说明
static String pathSeparator 依赖于系统的路径分隔符,String 类型的表示
static char pathSeparator 依赖于系统的路径分隔符,char 类型的表示

File类的构造方法:

签名 说明
File(File parent, String child) 根据父目录 + 孩子文件路径,创建一个新的 File 实例
File(String pathname) 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径
File(String parent, String child) 根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示

File类的方法:

1️⃣ 创建File对象

File(String pathname)

创建File对象的时候,就可以指定一个路径(绝对/相对均可)

 File f = new File("./test.txt");

2️⃣获取File对象父目录文件路径

f.getParent();

3️⃣获取File对象的纯文件名字

f.getName();

4️⃣获得File对象的相对路径

f.getPath();

5️⃣获得File对象的绝对路径

f.getAbsolutePath();

6️⃣返回 File 对象的修饰过的绝对路径

System.out.println(f.getCanonicalPath());

依次运行的结果:
File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第1张图片
7️⃣如果输入路径下的文件不存在,可以把文件创建出来:
File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第2张图片
File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第3张图片

8️⃣删除文件
File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第4张图片
createNewFile创建空文件
delete删除文件
deleteOnExit 进程退出时删除文件

9️⃣创建目录File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第5张图片

重命名

public class TestDemo5 {
    //重命名
    public static void main(String[] args) {
        File srcFire = new File("aaa.txt");
        File destFire = new File("bbb.txt");
        srcFire.renameTo(destFire);
    }
}

1️⃣1️⃣显示目录内容

public class TestDemo6 {
    //显示目录内容
    public static void main(String[] args) {
        File f = new File("./testDir");
        String[] results = f.list();
        System.out.println(Arrays.toString(results));
    }
}

方法总结:

修饰符及返回值类型 方法签名 说明
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() 判断用户是否对文件有可写权限

上述的文件操作,主要都是在操作 “文件系统” (操作系统中管理文件的核心功能)
新增文件/删除文件/新增目录/列出目录内容/重命名/获取路径…

针对文件内容操作,涉及到的关键操作,就是 读文件写文件 ~
在这里插入图片描述

stream

流(stream)
把读写文件操作,比喻成"水流"
水的特点,流动起来,绵延不断~
File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第6张图片
Java就在"流"的概念上,提供了一组类,完成读写文件的操作!
这组类,再按照不同的特点,再进行细分

  1. 字节流(以字节为基本单位),适用于二进制文件
    InputStream OutputStream (父类)
  2. 字符流(以字符为基本单位),适用于文本文件
    Reader Winter (父类)
    标准库中,给这些父类还提供了各种子类的实现,来适应不同场景下的读写操作!!

InputStream

InputStream要在构造方法中,确定一个文件~

InputStream inputStream = new FileInputStream("aaa.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() 关闭字节流

File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第7张图片

使用字节流读文件

  • read():
    读数据:把数据从硬盘读到内存中~
    read() 一次读一个字节,读出的结果作为read的返回值~
    read(byte[] b) 把读到的内容放到参数字节数组b中.
    read(byte[] b,int off, int len) 把读到的内容放到参数字节数组b中,从off开始放,放len长度.
    这里的参数b 用来存放方法读取到的结果
    此处的参数b被称为 “输出型参数”

代码演示:

InputStream是一个抽象类,不能实例化!

public class TestDemo7 {
    public static void main(String[] args) throws IOException {
    
       // 点进去发现是抽象类,只能实例化它的子类,
     //   这个实例化过程就相当于打开文件!!类似于C中的fopen,想操作就得先打开!
        InputStream inputStream = new FileInputStream("bbb.txt");
        while (true) {
            //一次读一个字节
            int b = inputStream.read();
            //文件读完了,返回值为-1
            if(-1 == b) {
                break;
            }
            System.out.print((char)b);
        }
        inputStream.close();
    }
}

File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第8张图片
在这里插入图片描述

使用Scanner读文件

  • Scanner():
    InputStream字节流,ScannerInputStream包装出了一个字符流
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;


public class Demo11 {
    //使用Scanner进行读操作
    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("./bbb.txt");
       
        //给Scanner传入一个流对象
        Scanner scanner = new Scanner(inputStream);
        while (scanner.hasNext()) {
            System.out.println(scanner.next());
        }
        inputStream.close();

    }
}

运行结果:
File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第9张图片
在这里插入图片描述

OutputStream

使用字节流写文件

  • wirte():
    File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第10张图片
    在这里插入图片描述

代码演示:

public class Demo8 {
    //进行写文件
    public static void main(String[] args) throws IOException {
        OutputStream outputStream = new FileOutputStream("./bbb.txt");
        //a.b.c的ascii 码
        outputStream.write(97);
        outputStream.write(98);
        outputStream.write(99);

        outputStream.close();

    }
}

File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第11张图片
❗❗注意:
使用OutputStream写文件的时候,只要打开文件成功,就会把原有文件清空
在这里插入图片描述

使用PrintWriter进行写操作

  • PrintWriter() :
import java.io.*;


public class Demo12 {
    //使用Pirntf来进行写操作
    public static void main(String[] args) throws IOException {
      OutputStream outputStream = new FileOutputStream("./bbb.txt");
      PrintWriter printWriter = new PrintWriter(outputStream);

      printWriter.println();
      printWriter.printf("a = %d\n",10);
      //刷新缓冲区
      printWriter.flush();
      outputStream.close();

    }
}


运行结果:
File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第12张图片
在这里插入图片描述

Reader

使用字符流读文件

  • read():
    File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第13张图片绿色的三个版本跟刚刚字节流InputStream 的三个read是一样的~
public class Demo9 {
    //使用字符流读文件
    public static void main(String[] args) throws IOException {
        Reader reader = new FileReader("./bbb.txt");
        while (true) {
            int ret = reader.read();
            if(-1 == ret) {
                break;
            }
            char a = (char) ret;
            System.out.println(a);
        }
        reader.close();
    }

}

File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第14张图片

我们使用字节流的时候,ret存的是ascii码,而使用字符流,ret存的就是字符本身了~
在这里插入图片描述

Wirter

使用字符流写文件

  • wirter():
    -File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第15张图片
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class Demo10 {
    //使用字符流写文件
    public static void main(String[] args) throws IOException {
        Writer writer = new FileWriter("./bbb.txt");
        writer.write("hello yuanyuan");
        writer.close();
    }
}

运行结果:
File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第16张图片
File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第17张图片

close()

在这里插入图片描述

❓为什么文件操作一定要进行close?

每个进程都对应着PCB(可能是多个)
PCB里面有一个字段,叫做文件描述表 ~~(同一个进程里,多个PCB共同使用同一份文件描述符表的)
这个文件描述表相当于是一个数组/顺序表. 进程每次打开一个文件,都会在这个表里,创建一个项~
这一项就表示一个文件!
如果关闭一个文件,就会把表里的对应项给释放掉~

如果不关闭,意味着这个表项就在这里占着位置,如果你持续打开文件,并且从来不关,此时就会导致表项被耗尽(最大长度是有上限的),最终导致后续再打开文件,就会打开失败!

这种严重的问题,就叫做文件资源泄露 !!!!(比程序崩溃还要严重!!)

JVM有自动释放的策略,对应的流对象如果被GC销毁了,是会自动关闭对应的文件(释放文件描述符表元素的)
但是这件事不一定会发生,如果代码写的有问题,仍然保持着流对象的引用,不触发GC,文件就得始终打开状态~

但如果写了close()也有可能会发生文件资源泄露的问题!
比如:

File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第18张图片
这个代码如果在close()前面抛出异常了,那么close就执行不到了!!!

客户端不害怕这种资源泄露问题(客户端程序用一会儿就关了)
服务器害怕这种问题(服务器需要长期运行)

保证close()一定会生效的办法是:

  1. 使用try finally:
    File 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第19张图片
    这样就能保证无论try里面发生了什么,close()都会执行到~
  2. 使用try-with-resourcesFile 类用法和 InputStream, OutputStream,Reader,Wirter 的用法_第20张图片把要关闭的对象写到try()里,当try结束,就会自动的调用到对应对象的close方法!!而且支持一个()放多个对象,多个对象的创建之间使用 ; 分割就行了~

总结

在这里插入图片描述

你可以叫我哒哒呀
本篇到此结束
“莫愁千里路,自有到来风。”
我们顶峰相见!

你可能感兴趣的:(jvm,java,linux)