java文件io详解(File类+操作文件内容的字符字节流)


前言


一、文件系统

1.文件的理解

文件=>在硬盘上存储数据的方式.
操作系统帮我们把硬盘的一些细节都封装起来了.程序猿只需要了解文件相关的接口即可.
硬盘用来存储数据,和内存相比,硬盘的存储空间更大,访问速度更慢,成本更低,持久化存储

不同的文件系统,管理文件的方式都是类似的
通过目录–文件构成了“N叉树"树形结构~~

站在操作系统的角度看待,目录也是文件.
操作系统中的文件是一个更广义的概念,具体来说里面有很多种不同的类型.
1.普通文件(通常见到的文件)
2.目录文件(通常见到的文件夹)

文件系统上存储的文件,具体来说又分成两个大类
1.文本文件
存储的是字符
2.二进制文件
二进制的数据.
一个最简单的方式,来判断文件是二进制还是文本。
直接使用记事本打开.
如果打开之后能看懂,文本.打开之后看不懂,二进制

路径

D盘=> tmp => cat.jpg通过这个路线就能找到/确定电脑上的唯一一个文件.这个东西就称为"路径"
windows上使用/或者\来分割不同的目录
若用\很容易被当成转义字符,如\tdg,\t就当成了制表符,要用\\tdg才对。(反斜杠)
一般用:/(正斜杠)

以盘符开头的路径,也叫做"绝对路径"
绝对路径相当于是从"此电脑"这里出发,找文件的过程
以.开头(当前所在目录)或者…开头(当前前的上一层目录)的路径,叫做"相对路径"
相对路径,需要有一个“基准目录"/"工作目录"表示从这个基准目录出发,怎么走能找到这个文件.

2.基于File类的文件系统操作

java.io.File
IO input和output
站在cpu的角度,来看待输入输出的:
在这里插入图片描述
通过File对象来描述一个具体的文件。File对象可以对应到一个真实存在的文件也可以对应到一个不存在的文件.
在这里插入图片描述

1.路径

import java.io.File;
import java.io.IOException;

public class file01 {
    public static void main(String[] args) throws IOException {
        File file=new File("c:/test.txt");
        System.out.println(file.getParent());
        System.out.println(file.getName());
        System.out.println(file.getPath());
        System.out.println(file.getAbsolutePath());//绝对路径
        System.out.println(file.getCanonicalPath());//整理后的绝对路径
    }
}

在这里插入图片描述
将file路径改变一下:

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

在这里插入图片描述

2.创建文件

public class file02 {
    public static void main(String[] args) throws IOException {
        File file=new File("./test.txt");
        file.createNewFile();//创建文件
        System.out.println(file.exists());
        System.out.println(file.isFile());//是否是文件
        System.out.println(file.isDirectory());//是否是目录

    }
}

在这里插入图片描述

3.删除文件

public class file03 {
    public static void main(String[] args) throws InterruptedException {
        File file=new File("./test.text");
        //file.delete();//1.删除
        file.deleteOnExit();//2.不是立即退出而是等程序退出了再删除
        Thread.sleep(5000);
    }
}

在这里插入图片描述

4.创建目录

public class file04 {
    public static void main(String[] args) {
        File file=new File("./testDir");
        file.mkdir();//一次创建一层目录
        //file.mkdirs();//一次创建多级目录
    }
}

public class file04 {
    public static void main(String[] args) {
        File file=new File("./testDir/111/222/444/33");
        //file.mkdir();//一次创建一层目录
        file.mkdirs();//一次创建多级目录
    }
}

在这里插入图片描述

5.文件重命名

文件重命名,也可以起到文件移动的效果.

public class file03 {
    public static void main(String[] args) throws InterruptedException {
        File file=new File("./test.txt");
        File file2=new File("./src/test2.txt");
        file.renameTo(file2);//移动到src中,然后重命名为test2
    }
}

二、文件内容的操作

1.文件流. stream

虽然不同的编程语言操作文件的 api有所差别,这里的基本步骤都是一样的.文件内容的操作核心步骤,有四个:
在这里插入图片描述
Java lO流是一个比较庞大的体系,涉及到非常多的类.这些不同类,都有各自不同的特性.但是总的来说,使用方法都是类似的.
1)构造方法,打开文件.
2) close方法,关闭文件.
3)如果衍生自InputStream 或者Read,就可以使用read方法来读数据.
4)如果衍生自OutputStream 或者Writer就可以使用write方法来写数据了.

2.字符流

Reader、Writer
后续操作字符的类,衍生自这两个类.
操作字符为单位.(文本文件)

1.打开文件

public class file06 {
    public static void main(String[] args) throws IOException {
        //FileReader构造方法,可以填写一个文件路径,也可以填写一个构造好的File对象
        Reader reader=new FileReader("c:/11/test.txt");//Reader是抽象类,用FileReader
        reader.close();//释放资源,非常重要
    }
}

在这里插入图片描述
但是上面很可能因为各种原因执行不到close。
因此,为了使确定能执行到,可以用try{代码逻辑}finally{close}
也可以使用try with resources是更好的方式
只要try执行完毕,就会自动调用到close方法。

public class file06 {
    public static void main(String[] args) throws IOException {
        //FileReader构造方法,可以填写一个文件路径,也可以填写一个构造好的File对象
       try( Reader reader=new FileReader("c:/11/test.txt")) {//Reader是抽象类,用FileReader
       }
    }
}

2.读文件

在这里插入图片描述
在这里插入图片描述
通过read,就会把本来是一个空的数组,填充上内容.
在这里插入图片描述

public class file06 {
    public static void main(String[] args) throws IOException {
        //FileReader构造方法,可以填写一个文件路径,也可以填写一个构造好的File对象
       try( Reader reader=new FileReader("c:/11/test.txt")) {//Reader是抽象类,用FileReader
           while(true) {//读多次
               char buf[] = new char[1024];
               int n = reader.read(buf);//n表示你实际读到的字符个数
               if(n==-1){
                   break;//读到文件末尾
               }
               for (int i = 0; i < n; i++) {
                   System.out.print(buf[i]+", ");
               }
           }
       }
    }
}

也可以用此种方法来读
在这里插入图片描述
在这里插入图片描述

3.字节流

InputStream、OutputStream
后续的一些操作字节的类都是衍生自这两个类
是操作字节为单位.(二进制文件)

1.读文件

InputStream是字节流,用法和Reader非常相似.
文本文件,也可以使用字节流打开.只不过此时你读到的每个字节,就不是完整字符了.
在这里插入图片描述

public class file07 {
    public static void main(String[] args)throws IOException {
        try(InputStream inputStream=new FileInputStream("c:/11/test.txt")) {
            while (true) {
                byte[] buf = new byte[1024];
                int n = inputStream.read(buf);
                if (n == -1) {
                    break;
                }
                for (int i=0;i<n;i++){
                    System.out.printf("%x ",buf[i]);
                }
            }

        }
    }
}

在这里插入图片描述

java 虽然有char,很少会用.更多的是使用String

public class file07 {
    public static void main(String[] args)throws IOException {
        try(InputStream inputStream=new FileInputStream("c:/11/test.txt")) {
            while (true) {
                byte[] buf = new byte[1024];
                int n = inputStream.read(buf);
                if (n == -1) {
                    break;
                }
               // for (int i=0;i<n;i++){
                    //System.out.printf("%x ",buf[i]);
               // }
                String s=new String(buf,0,n,"utf8");
                System.out.println(s);
            }
        }
    }
}

上面把字符转换为字符串太麻烦了!
此处,借助Scanner类,就可以完成字节/字符=>字符串转换

操作系统中,“文件"是一个广义的概念。普通的硬盘上的文件,也是文件,后面网络编程,网卡(socket),也是文件。
System.in是一个特殊的文件,对应到"标准输入”。是字节流。inputStream也是字节流。可以直接替换。
Scanner都是一视同仁的.只是把当前读到的字节数据进行转换

public class file08 {
    public static void main(String[] args)throws IOException {
        try(InputStream inputStream=new FileInputStream("c:/11/test.txt")){
            Scanner scanner=new Scanner(inputStream);
            String s=scanner.next();
            System.out.println(s);
        }
    }
}



2.写文件

输出,使用方法和输入非常相似.关键操作是 write.
write之前要打开文件,用完了也需要关闭文件.
输出流对象(无论字节流还是字符流)会在打开文件之后,清空文件内容!!

public class file09 {
    public static void main(String[] args)throws IOException {
        try (Writer writer=new FileWriter("c:/11/test.txt")){
            writer.write("hellodkjs");//write可以一次写一个字符串
        }
    }
}

还可以按照追加写方式打开,此时就不会清空内容了
在这里插入图片描述

文件IO相关代码题

1.写一个代码递归遍历目录

题目:扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件

深度优先 DFS先序/中序/后序(递归)
广度优先 BFS层序(队列)

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

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

        //1.让用户输入一个目录,后续查找都是基于这个目录
        System.out.println("请输入要搜索的目录:");
        File rootPath=new File(scanner.next());
        //2.让用户输入要搜索要删除的关键词
        System.out.println("请输入要删除的关键词");
        String word=scanner.next();

        //3.判断一下当前输入的目录是否有效
        if (!rootPath.isDirectory()){
            System.out.println("你此时输入的不是一个合法目录");
            return;
        }
        //3.遍历目录,从根目录出发按照深度优先的方式进行遍历
        scanDir(rootPath,word);
    }
    public static void scanDir(File currentDir,String word){
        //1.先列出当前目录中都包含哪些内容
       File[] files= currentDir.listFiles();
       if(files==null||files.length==0){
           return;//非法或空目录
       }
       //2.遍历
        for(File f:files){
            //加个日志,方便看文件执行过程
            System.out.println(f.getAbsolutePath());
            if(f.isFile()){
                //3.如果当前文件是普通文件,看文件名是否包含word,来决定是否删除
                dealFile(f,word);
            }else {
                //4.如果是目录文件迅速scanDir
                scanDir(f,word);
            }
        }
    }

    private static void dealFile(File f, String word) {
        //1.先确定当前文件名是否包含word
        if(!f.getName().contains(word)){
            return;//不包含
        }
        //2.包含,询问用户是否要删除文件
        System.out.println("该文件是:"+f.getAbsolutePath()+",是否要删除?(Y/N)");
        String choice=scanner.next();
        if (choice.equals("Y")||choice.equals("y")){
            f.delete();
        }
        //如果是其他值都忽略
    }

}

在这里插入图片描述

2.进行普通文件的复制

把一个文件,复制成另一个文件。
把文件A复制成文件B。打开A,依次读出每个字节,再写入到文件B就行了.

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

//完成文件复制
public class file11 {
    public static void main(String[] args)throws IOException {
        Scanner scanner=new Scanner(System.in);
        //1.输入路径并合法性判断
        System.out.println("请输入要复制的文件路径:" );
        String src=scanner.next();

        File srcFile=new File(src);
        if (!srcFile.isFile()){
            System.out.println("您输入的源路径非法!");
            return;
        }
        System.out.println("请输入要复制的目标路径:");
        String dest=scanner.next();
        File destFile=new File(dest);
        //不要求目标文件本身存在,但得保证目标文件的目录是存在的
        if(!destFile.getParentFile().isDirectory()){
            System.out.println("您输入的目标文件路径是非法的");
            return;
        }
        //2.进行复制操作的过程,按字节流打开
        try(InputStream inputStream=new FileInputStream(srcFile);
            OutputStream outputStream=new FileOutputStream(destFile)) {
            while (true){
                byte[] buffer=new byte[1024];
                int n=inputStream.read(buffer);
                System.out.println("n="+n);
                if (n == -1) {
                    System.out.println("读取到eof,循环结束");
                    break;
                }
                outputStream.write(buffer,0,n);

            }
        }
    }
}

在这里插入图片描述

在这里插入图片描述

总结

  • 20
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值