【文件操作】IO

目录

一 文件

1.文件的定义

2.File类

二 文件系统的操作

1.属性

2.构造方法

3.常用方法

三 文件内容的操作

1.字节流

2.字符流

四 练习


一 文件

1.文件的定义

1.狭义的文件

指的是硬盘上的文件和目录(文件夹)。

2.广义的文件

泛指计算机中很多的软硬件资源。操作系统中把很多的硬件设备和软件资源抽象成了文件,按照文件的方式来统一管理。

3.文件的类型

文本文件:存的是文本、字符串

二进制文件:存的是二进制数据,不一定是字符串了

4.路径

绝对路径:以C: 、D:盘符开头的路径

相对路径:当前所在的目录(工作目录)为基准,以 . 或  .. 开头找到指定路径 

2.File类

Java对于文件的操作

1.针对文件系统操作:文件的创建,删除,重命名...

2.针对文件内容操作:文件的读和写

二 文件系统的操作

Java标准库中提供了File这个类

😶‍🌫️属性

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

😶‍🌫️构造方法

😶‍🌫️常用方法

deleteOnExit程序退出的时候,自动删除-->程序中需要使用一些"临时文件"的时候需要用到

三 文件内容的操作

针对文件内容,是使用"流对象"来进行读写的。比如通过水龙头接100ml水,可以一次接100ml,可以分两次接50ml,也可以分10次接10ml。

如果从文件中读100个字节,可以一次性读100字节,可以分两次读50字节,也可以分10次读10字节,写文件同理。

Java标准库中的流对象从类型上分为两大类:字节流(操作二进制数据)和字符流(操作文本数据)。

操作步骤:

1.打开文件(构造对象)

2.关闭文件(close)

3.读文件(read)-->针对InputStream/Reader

4.写文件(write)-->针对OutputStream/Writer

InputStream/OutputStream/Reader/Writer都是抽象类,不能直接new

1.字节流

😶‍🌫️InputStream

❤️理解read的行为和返回值:

read会尽可能的把参数传进来的数组填满,上面希望读取的长度是1024,read会尽可能的读取1024个字节到数组中。但实际上文件剩余的长度有限,如果剩余的长度大于1024个字节,那么都会被1024字节填上;反之剩余长度不足1024,那么有多少就填多少,read方法会返回实际读取长度

❤️buffer存在的意义:为了提高IO的效率

单次IO操作要访问硬盘/IO设备,比较消耗时间。如果频繁进行IO操作耗时就更多了。如果能缩短IO操作的次数,就可以提高整体效率。

第一个版本的代码,一次只读一个字节,循环次数多,read次数也多,效率低耗时多。

第二个版本的代码,一次读1024个字节,循环次数大大降低,read次数少了,效率变高耗时减少。

注意区分:cache(缓存),buffer(缓冲区)

😶‍🌫️OutputStream

关于close:

进程内容提到过:在内核中,使用PCB这样的数据来表示进程

一个线程对应一个PCB

一个进程可以对应1-n个PCB

PCB中有一个重要的属性->文件描述符表(相当于一个数组),记录了进程打开了哪些文件

如果close没有写会怎么样?

如果没有close,意味着文件描述符表很快就会被占满了(这个数组不会自动扩容,存在上限),那么之后再次打开文件就会失败。

怎么确保close被执行到?

一般来说close是要执行的,但是如果一个程序里的文件自始至终都要使用不关闭问题也不大。因为随着进程结束,PCB销毁,文件描述符表也被销毁了,对应的资源也就被操作系统自动回收了。

2.字符流

😶‍🌫️Reader

😶‍🌫️Writer

😶‍🌫️Scanner

四 练习

1.扫描指定目录,并找到名称中包含指定字符的所有文件(不包含目录),并且询问用户是否删除文件。

步骤:

1.用户输入一个目录

2.判断用户输入的目录是否有效

3.用户输入要删除的文件名

4.对指定目录进行扫描,递归

注意:

public class IODemo {
    private static Scanner sc = new Scanner(System.in);
    public static void main(String[] args) {
        //1.让用户输入一个指定搜索的目录
        System.out.println("请输入要搜索的路径:");
        String basePath = sc.next();

        //2.针对用户的输入进行简单判断
        File root = new File(basePath);
        if(!root.isDirectory()){
            //路径不存在或者只是一个普通文件,则无法进行搜索
            System.out.println("输入的目录有误!");
            return;
        }
        //3.再让用户输入一个要删除的文件名
        System.out.println("请输入要删除的文件名");
        String nameTodelete = sc.next();

       /*针对指定路径进行扫描,递归操作
       * 先从根目录出发,如果当前目录包含要删除的文件就删除,否则就到下一个
       * 如果当前位置包含了一些目录,再对子目录进行递归*/
        scanDir(root, nameTodelete);
    }

    private static void scanDir(File root, String nameTodelete) {
        System.out.println("[scanDir]" + root.getAbsolutePath());
        //1.先列出root下的文件和目录
        File[] files = root.listFiles();
        if(files == null){
            return;//空目录
        }
        //2.遍历当前列出结果
        for(File f : files){
            if(f.isDirectory()){
                //如果是目录就进一步递归
                scanDir(f, nameTodelete);
            }else{
                //如果是普通文件则判断要不要删除
                if(f.getName().contains(nameTodelete)){
                    System.out.println("确认是否要删除" + f.getAbsolutePath() + "吗?");
                    String choice = sc.next();
                    if(choice.equals("y") || choice.equals("Y")){
                        f.delete();
                        System.out.println("删除成功!");
                    }else{
                        System.out.println("删除取消!");
                    }
                }
            }
        }
    }
}

2.进行普通文件的复制

步骤:

1.用户输入源和目标路径

2.检查源文件是否存在并且是一个文件

3.检查目标文件是否存在

4.进行拷贝操作

public class IODemo12 {
    public static void main(String[] args) {
        //1.输入两个路径:源路径和目标路径(从哪来拷贝到哪去)
        Scanner sc = new Scanner(System.in);
        System.out.println("要拷贝的文件:");
        String srcPath = sc.next();
        System.out.println("要拷贝到:");
        String destPath = sc.next();
        
        File srcFile = new File(srcPath);
        if(!srcFile.isFile()){
            //如果源不是文件而是目录或不存在,不做任何操作
            System.out.println("输入的源路径有误!");
            return;
        }
        File destFile = new File(destPath); 
        if(destFile.isFile()){
            //如果目标已经存在也不能拷贝
            System.out.println("输入的目标路径有误!");
            return;
        }
        
        //2.进行拷贝操作
        try(InputStream inputStream = new FileInputStream(srcFile);
            OutputStream outputStream = new FileOutputStream(destFile)){
            //进行文件读写操作
            while(true){
                int b = inputStream.read();
                if(b == -1){
                    break;
                }
                outputStream.write(b);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值