File 类的用法和文件内容的操作

本文详细介绍了Java中File类的使用,包括对文件和目录的操作,如创建、删除、读取属性等。接着讨论了字节流InputStream和OutputStream的read方法及其应用,字符流Reader和Writer在读写文件中的角色,以及Scanner的便捷读取方式。文章还提到了资源关闭的优化,如try-with-resource语句的使用,以及System类的in和out属性在输入输出中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

🎉🎉🎉点进来你就是我的人了
博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!

人生格言:当你的才华撑不起你的野心的时候,你就应该静下心来学习!

欢迎志同道合的朋友一起加油喔🦾🦾🦾
目标梦想:进大厂,立志成为一个牛掰的Java程序猿,虽然现在还是一个🐒嘿嘿
谢谢你这么帅气美丽还给我点赞!比个心


目录

1.File类

1.1 File类对文件进行操作

1.2 File类对目录进行操作

字符流和字节流

2. 读文件 

2.1 字节流-InputStream / FileInputStream

🍔read() 代码示例

🍔read(byte[] b)代码示例

2.2 字符流-Reader / FileReader

2.3 通过 Scanner 进行字符读取

2.4 关闭资源的优化

3.写文件

3.1 字节流-OutputStream / FileOutputStream

3.2 字符流-Writer / FileWriter

 3. System类的使用

4.try-with-resource语句



1.File类

在java程序中操纵 文件/目录 ?怎么办?
java程序,最典型的特点,面向对象,java程序最擅长的就是操作对象,盘符上的文件/目录,将它的各种信息进行了封装,封装为一个对象,
java程序最擅长的就是操纵对象,这个对象属于 ---》File类

盘符上的文件---》封装为对象---》对象属于File类的对象--》有了这个对象,我们程序就可以直接操纵这个对象,通过这个对象获取文件的各种信息,还可以对文件进行创建 ,删除。

File概述

在java中提供了一个File类通过这个类来完成文件系统的相关操作例如:

1)列出目录中有哪些文件

2)创建文件

3)创建目录

4)删除文件

5)重命名文件

这个File类就描述了一个文件/目录,通过这个对象就可以实现以上的功能

File属性

修饰符及类型 

属性说明
static StringpathSeparator依赖于系统的路径分隔符 '/',String 类型的表示
static charpathSeparator依赖于系统的路径分隔符 '/',char 类型的表示

构造方法

方法 

说明

File(File parent, String

child)

根据父目录 + 孩子文件路径,创建一个新的 File 实例
File(String pathname)

根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径

File(String parent, String

child)

根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示

  方法

修饰符及返回 值类型

方法说明
String

getParent()

返回 File 对象的父目录文件路径
StringgetName()

返回 FIle 对象的纯文件名称

StringgetPath()返回 File 对象的文件路径
StringgetAbsolutePath()返回 File 对象的绝对路径

String

getCanonicalPath()返回 File 对象的修饰过的绝对路径
booleanexists()判断 File 对象描述的文件是否真实存在
booleanisDirectory()

判断 File 对象代表的文件是否是一个目录

booleanisFile()判断 File 对象代表的文件是否是一个普通文件
booleancreateNewFile()

根据 File 对象,自动创建一个空文件。成功创建后返回 true

booleandelete()根据 File 对象,删除该文件。成功删除后返回 true
voiddeleteOnExit()

根据 File 对象,标注文件将被删除,删除动作会到 JVM 运行结束时才会进行

String[]list()返回 File 对象代表的目录下的所有文件名
File[]listFiles()

返回 File 对象代表的目录下的所有文件,以 File 对象表示

booleanmkdir()创建 File 对象代表的目录
booleanmkdirs()

创建 File 对象代表的目录,如果必要,会创建中间目录

boolean  

renameTo(File   dest)

进行文件改名,也可以视为我们平时的剪切、粘贴操作

booleancanRead()

判断用户是否对文件有可读权限

booleancanWrite()判断用户是否对文件有可写权限

绝对路径:以盘符开头的路径,称为 "绝对路径"。

相对路径:以 . 或者 .. 开头的路径称为 "相对路径"。


1.1 File类对文件进行操作

public class Test01 {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) throws IOException {
        //将文件封装为一个File类的对象:
        File f = new File("d:\\test.txt");
        File f1 = new File("d:\\test.txt");
        File f2 = new File("d:/test.txt");
        //File.separator属性帮我们获取当前操作系统的路径拼接符号
       //在windows,dos下,系统默认用“\”作为路径分隔符 ,在unix,url中,使用“/”作为路径分隔符。
        File f3 = new File("d:"+File.separator+"test.txt");//建议使用这种
        //常用方法:
        System.out.println("文件是否可读:"+f.canRead());
        System.out.println("文件是否可写:"+f.canWrite());
        System.out.println("文件的名字:"+f.getName());
        System.out.println("上级目录:"+f.getParent());
        System.out.println("是否是一个目录:"+f.isDirectory());
        System.out.println("是否是一个文件:"+f.isFile());
        System.out.println("是否隐藏:"+f.isHidden());
        System.out.println("文件的大小:"+f.length());
        System.out.println("是否存在:"+f.exists());
        /*if(f.exists()){//如果文件存在,将文件删除操作
            f.delete();
        }else{//如果不存在,就创建这个文件
            f.createNewFile();
        }*/
        System.out.println(f == f1);//比较两个对象的地址
        System.out.println(f.equals(f1));//比较两个对象对应的文件的路径
        //跟路径相关的:
        System.out.println("绝对路径:"+f.getAbsolutePath());
        System.out.println("相对路径:"+f.getPath());
        System.out.println("toString:"+f.toString());
        System.out.println("----------------------");
        File f5 = new File("demo.txt");
        if(!f5.exists()){
            f5.createNewFile();
        }
        //绝对路径指的就是:真实的一个精准的,完整的路径
        System.out.println("绝对路径:"+f5.getAbsolutePath());
        //相对路径:有一个参照物,相对这个参照物的路径。
        //在main方法中,相对位置指的就是:D:\IDEA_workspace\TestJavaSE
        //在junit的测试方法中,相对路径指的就是模块位置
        System.out.println("相对路径:"+f5.getPath());
        //toString的效果永远是  相对路径
        System.out.println("toString:"+f5.toString());
        File f6 = new File("a/b/c/demo.txt");
        if(!f5.exists()){
            f5.createNewFile();
        }
        System.out.println("绝对路径:"+f6.getAbsolutePath());
        System.out.println("相对路径:"+f6.getPath());
    }
}

1.2 File类对目录进行操作

public class Test02 {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        //将目录封装为File类的对象:
        File f = new File("D:\\IDEA");
        System.out.println("文件是否可读:"+f.canRead());
        System.out.println("文件是否可写:"+f.canWrite());
        System.out.println("文件的名字:"+f.getName());
        System.out.println("上级目录:"+f.getParent());
        System.out.println("是否是一个目录:"+f.isDirectory());
        System.out.println("是否是一个文件:"+f.isFile());
        System.out.println("是否隐藏:"+f.isHidden());
        System.out.println("文件的大小:"+f.length());
        System.out.println("是否存在:"+f.exists());
        System.out.println("绝对路径:"+f.getAbsolutePath());
        System.out.println("相对路径:"+f.getPath());
        System.out.println("toString:"+f.toString());
        //跟目录相关的方法:
        File f2 = new File("D:\\b\\b\\c");
        File f3 = new File("D:\\c\\b\\c");
        //创建目录:
//        f2.mkdir();//创建单层目录
        f2.mkdirs();//创建多层目录
        //删除:如果是删除目录的话,只会删除一层,并且前提:这层目录是空的,里面没有内容,如果内容就不会被删除
        f2.delete();
        //查看:
        String[] list = f.list();//文件夹下目录/文件对应的名字的数组
        for(String s:list){
            System.out.println(s);  //只能输出文件名
        }
        System.out.println("=========================");
        File[] files = f.listFiles();//作用更加广泛
        for(File file:files){
                                                                                                                                //能通过对象去获取名字和路径等等
            System.out.println(file.getName()+","+file.getAbsolutePath());
        }
    }
}

字符流和字节流

 文本文件:.txt   .java  .c  .cpp  ---》建议使用字符流操作
非文本文件:.jpg,  .mp3  ,   .mp4 , .doc  , .ppt  ---》建议使用字节流操作

2. 读文件 

2.1 字节流-InputStream / FileInputStream

针对文件内容,使用“流对象”来进行操作。Java标准库中的流对象,从类型上分为字节流操作二进制数据的和字符流操作文本数据的。字节流中,又存在InputStream和OutputStream两个抽象类。

 InputStream方法:

修饰符及返回值类

方法说明

int

read()读取一个字节的数据,返回 -1 代表已经完全读完了

int

read(byte[] b)

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

量;返回 -1 代表以及读完了

int

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

读数据到 b 数组中,从  b[ off ]   开始放,返

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

void

close()

关闭字节流

 InputStream只是一个抽象类,要使用还要具体的实现类,对于文件读取来说,通常使用FileInputStream,其构造方法如下:

方法名说明
FilelnputStream (File file)利用File构造文件输入流
FilelnputStream (String name)利用文件路径构造文件输入流

🍃打开文件 

InputStream inputStream = new FileInputStream("test2.txt");
  • 对于这一行代码,打开文件成功后,就得到了 InputStream 对象,后续针对文件的操作,就都是通过这个对象展开的。
  • 再者,我们操作硬盘不方便直接操作,在内存里构造一个和它关联的对象,操作这个对象就相当于操作硬盘数据。

上述操作对象相当于操作硬盘数据,就类似于遥控器,我们开空调的时候,不可能每次借助梯子爬上去,用手摁下空调开关,而是通过空调遥控器去操作空调。

🍃关闭文件

inputStream.close();  
// 此处会抛出一个 IOException,对于打开文件抛出的文件找不到异常,IOException是其父类

为什么要关闭文件??

关闭文件主要是为了释放文件描述符表资源。

文件描述符表,这个表就相当于是个数组,这个数组的下标就称为 "文件描述符",每次打开一个文件,都会在文件描述符表中占据一个位置;每次关闭文件,都会释放一个位置。并且文件描述符表,是存在上线的,如果一个进程,一直在打开文件,没有释放,此时就会导致我们的进程在进行后续打开文件操作的时候,就会打开文件失败!!

🍃读取文件

🍔read() 代码示例

    public static void main(String[] args) throws IOException {
        // 1.打开文件
        InputStream inputStream = new FileInputStream("test2.txt");
 
        // 2.读取文件
        while(true) {
            int b = inputStream.read();
            if(b == -1) {
                // 文件读完了
                break;
            }
            // 因为 ASCII 码值以字节为单位存储,所以这里输出的是每个单词对应的 ASCII 码值
            System.out.println(b); // hello 对应的 ASCII 码值
        }
        
        // 3.关闭文件
        inputStream.close();
    }

🍔read(byte[] b)代码示例

    public static void main(String[] args) throws IOException {
        // 1.打开文件
        InputStream inputStream = new FileInputStream("test2.txt");
        
        // 2.读取文件
        byte[] buf = new byte[1024];
        // 返回的长度(字节)
        int len = inputStream.read(buf);
        System.out.println(len);
        for(int i = 0; i < len; i++) {
            System.out.println(buf[i]);
        }
        // 3.关闭文件
        inputStream.close();
    }

注意: 如果是读取中文,UTF8 的编码格式,一个汉字占3个字节。

如果要想读取中文在控制台,字节流只能通过指定编码格式,就比较麻烦。例如以下代码:

    public static void main(String[] args) throws IOException {
        // 1.打开文件
        InputStream inputStream = new FileInputStream("test2.txt");
 
        // 2.读取文件
        byte[] buf = new byte[1024];
  
        int len = inputStream.read(buf);
        String s = new String(buf, 0, len, "UTF8");
        System.out.println(s);
 
        // 3.关闭文件
        inputStream.close();
    }

2.2 字符流-Reader / FileReader

这里的方法和上面的 InputStream 相似就不过多介绍了。

🍔读取中文代码示例

    public static void main(String[] args) throws IOException {
        // 字符流
        Reader reader = new FileReader("test2.txt");
        char[] buffer = new char[1024];
        int len = reader.read(buffer);
        for(int i = 0; i < len; i++) {
            System.out.println(buffer[i]);
        }
        reader.close();
    }

虽然字符流读取中文比纯字节流好使一些,但还是不够方便。对于文本文件,还有更简单的写法。

2.3 通过 Scanner 进行字符读取

🍁Scanner 构造方法

构造方法

说明
Scanner(InputStream is, String charset)

使用 charset 字符集进行 is 的扫描读取

(也可以不指定编码格式,使用默认编码格式)

代码示例

    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("test2.txt");
        Scanner scanner = new Scanner(inputStream);
        // 想读什么类型就用 scanner 去调用什么
        String s = scanner.next();
        System.out.println(s);
        inputStream.close();
    }

2.4 关闭资源的优化

我们在前面字节流读取中文的代码中,发现如果在 read() 读文件的过程中出现异常,就可能导致 close() 执行不到,按照我们以前的思路,使用 try...catch...finally,将关闭资源放在 finally 中。

    public static void main(String[] args) {
        InputStream inputStream = null;
        try {
            // 打开文件(字节流)
            inputStream = new FileInputStream("test2.txt");
            byte[] buf = new byte[1024];
            int len = inputStream.read(buf);
            // 读取中文
            String s = new String(buf, 0, len, "UTF8");
            System.out.println(s);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

如果这样做的话,我们的代码显得又臭又长,更推荐的做法是以下做法:

    public static void main(String[] args) {
        try (InputStream inputStream = new FileInputStream("test2.txt")) {
 
            byte[] buf = new byte[1024];
            int len = inputStream.read(buf);
            // .........
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

这种语法机制叫做 try with resources,这个操作就会在 try 执行结束后,自动调用 inputStream 的 close 方法(实现 Closeable 接口的类才能这样做)。

3.写文件

3.1 字节流-OutputStream / FileOutputStream

【方法】

修饰 符及 返回 值类 

方法说明

void

write(int b)写入要给字节的数据

void

write(byte[] b)

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

write(byte[] b, int off,

int len)

将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个
voidclose()关闭字节流

void

flush()I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。

 OutputStream也是一个抽象类,要使用需要具体的实现类,而对于写入文件来说,使用FIleOutputStream。

🍃代码示例

    public static void main(String[] args) {
        try(OutputStream outputStream = new FileOutputStream("test2.txt")) {
            // 方法一
            /* outputStream.write('h');
            outputStream.write('e');
            outputStream.write('l');
            outputStream.write('l');
            outputStream.write('o'); */
 
            // 方法二
            String s = " hello java";
            outputStream.write(s.getBytes());
            // 把旧的文件内容清空,重新去写
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

注意:每次重新写的时候,都会把旧的文件内容清空掉,重新去写。

但是这种原生字节流的写文件方法,用起来还是不方便。

3.2 字符流-Writer / FileWriter

🍃代码示例

    public static void main(String[] args) {
        try (Writer writer = new FileWriter("test2.txt")) {
            // 能写字符串,就很方便
            writer.write("hello world");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

我们的这个字符流中的 Writer 还能写字符串,就很方便。还有一种方式 -- PrintWriter ,它提供了更丰富的写。

PrintWriter 代码示例

    public static void main(String[] args) {
        try (OutputStream outputStream = new FileOutputStream("test2.txt")) {
            PrintWriter printWriter = new PrintWriter(outputStream);
            printWriter.println("hello");
            printWriter.println("你好");
            printWriter.printf("%d: %s\n", 1, "Java");
            // println 需要搭配 flush 使用
            printWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

🍃这里要注意 PrintWrite 是自带缓冲区的,缓冲区是时候会被刷新到硬盘中呢?

🍃1.缓冲区满了;2.显示调用 flush 方法

所以我们在调用 println 写文件的时候,务必记得 flush 刷新

 3. System类的使用

【1】System的属性:
        System.in  : “标准”输入流。---》默认情况下  从键盘输入
        System.out  :“标准”输出流。 ---》默认情况下,输出到控制台。
【2】System.in :“标准”输入流。---》默认情况下  从键盘输入

public class Test01 {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) throws IOException {
        //得到的是标准的输入流:--》从键盘输入:
        //InputStream in = System.in;
        //调用方法:
        //int n = in.read();//read方法等待键盘的录入,所以这个方法是一个阻塞方法。
        //System.out.println(n);
        //以前案例:从键盘录入一个int类型的数据:
        //从上面的代码证明,键盘录入实际上是:System.in
        //形象的理解:System.in管,这个管怼到键盘上去了,所以你从键盘录入的话,就从这个管到程序中了
        //Scanner的作用:扫描器:起扫描作用的,扫键盘的从这根管出来的数据
        /*Scanner sc = new Scanner(System.in);
        int i = sc.nextInt();
        System.out.println(i);*/
        //既然Scanner是扫描的作用,不一定非得扫 System.in进来的东西,还可以扫描其他管的内容:
        Scanner sc = new Scanner(new FileInputStream(new File("d:\\Test.txt")));
        while(sc.hasNext()){
            System.out.println(sc.next());
        }
    }
}

【3】System.out  : 返回的输出流 、 打印流(PrintStream)

public class Test02 {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        //写到控制台:
        PrintStream out = System.out;
        //调用方法:
        out.print("你好1");//直接在控制台写出,但是不换行
        out.print("你好2");
        out.print("你好3");
        out.print("你好4");
        out.println("我是中国人1");//直接在控制台写出,并且换行操作
        out.println("我是中国人2");
        out.println("我是中国人3");
        out.println("我是中国人4");
        System.out.println("你是");
        System.out.print("中国人");
    }
}

4.try-with-resource语句

try-with-resources是Java 7中引入的一个特性,它是为了简化在程序中使用资源(例如文件、网络连接等)的管理。在Java程序中,资源的正确关闭非常重要,因为资源泄漏可能导致性能问题、程序错误或其他问题。try-with-resources语句确保在代码块执行完毕后自动关闭资源,无论代码执行过程中是否发生异常。

try-with-resources语句实现自动关闭资源的方式是通过在资源实现java.lang.AutoCloseablejava.io.Closeable接口的情况下,确保close()方法被调用。这两个接口都包含一个close()方法,它们的实现负责释放资源。

try-with-resources语句的基本结构如下:

try (ResourceType resource = new ResourceType()) {
    // 使用资源的代码
} catch (Exception e) {
    // 处理异常的代码
}

当程序执行到try语句块结束时,如果resource实现了AutoCloseableCloseable接口,那么close()方法将被自动调用。这确保了无论try块中是否抛出异常,资源都会被正确关闭。

因此,try-with-resources语句可以自动关闭资源,主要是因为它依赖实现AutoCloseableCloseable接口的资源,使得在try语句块结束时自动调用close()方法。这简化了资源管理,降低了资源泄漏和相关问题的风险。

注意:如果一个资源没有实现AutoCloseableCloseable接口,那么try-with-resources语句将无法自动关闭该资源。在这种情况下,你需要在代码中手动管理资源的关闭。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书生-w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值