【文件的操作和IO】

一、操作文件的属性

Java标准库提供可以操作文件的类:File

1.File类里面的方法

import java.io.File;
import java.io.IOException;
public class Test03 {
    public static void main(String[] args) throws IOException {
        File file=new File("./test01");
        System.out.println("获取文件的名字"+file.getName());
        System.out.println("获取文件路径"+file.getPath());
        System.out.println("获取文件的绝对路径"+file.getAbsoluteFile());//当前目录+new File()括号里面的内容
        System.out.println("获取文件的绝对路径"+file.getCanonicalFile());
        System.out.println("文件是否存在"+file.exists());
        System.out.println("文件是否是目录"+file.isDirectory());
        System.out.println("是否是文件"+file.isFile());
    }
}

在这里插入图片描述

2.删除文件file.delete():删除成功:true;删除失败:false

import java.io.File;

public class Test06 {
    public static void main(String[] args) throws InterruptedException {
        File file=new File("F:\\Test_2_4\\Test01\\test01.doc");
        System.out.println("文件是否存在"+file.exists());
        Thread.sleep(1000);
        //删除文件
        System.out.println(file.delete());
    }
}

在这里插入图片描述

删除文件:deleteOnExit():当整个程序执行完了之后,才会关闭文件

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

public class Test08 {
    public static void main(String[] args) throws IOException, InterruptedException {
        File file=new File("F:\\Test_2_4\\Test01\\demo001.doc");
        System.out.println("1.是否存在文件"+file.exists());
        file.createNewFile();
        System.out.println("2.是否存在文件"+file.exists());
        Thread.sleep(3000);
        //程序先执行完,然后文件删除
        file.deleteOnExit();
        System.out.println("3.是否存在文件"+file.exists());//先执行这个代码,等到整个程序执行完了之后,才删除文件
        System.out.println("程序执行结束");
    }
}

在这里插入图片描述

3.新增文件createNewFile()

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

public class Test07 {
    public static void main(String[] args) throws IOException {
        File file=new File("F:\\Test_2_4\\Test01\\test01.doc");
        System.out.println("文件是否存在"+file.exists());
        System.out.println("删除文件是否成功"+file.delete());
        //看当前路径下这个文件是否存在,如果不存在就创建,如果存在该文件,执行这个代码,不会产生新的文件
        file.createNewFile();
        System.out.println(file.getAbsolutePath());

    }
}

在这里插入图片描述

4.获取一个路径下的所有文件

思路:递归调用
首先,判断是文件还是文件夹,文件直接加到list当中,如果是文件夹,就获取该目录下所有的文件名,递归调用获取文件的方法。

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Test05 {
    public static List<File> files=new ArrayList<>();
    public static List<File> getFile(String path){
        File f=new File(path);
        if(f.isFile()){
            files.add(f);
        }else if(f.isDirectory()){
            String[] result=f.list();
            for(String s:result){
                getFile(path+"/"+s);
            }
        }
        return files;
    }
    public static void main(String[] args) {
        String path="F:\\Test_2_4";
        List<File> files=getFile(path);
        for (File file:files){
            System.out.println(file.getAbsolutePath());
        }
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.创建目录mkdir():只支持创建一层目录

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

public class Test09 {
    public static void main(String[] args) throws IOException {
        File file=new File("F:\\Test_2_4\\Test01\\Test002\\a");
        System.out.println("1.是否存在目录"+file.exists());
        file.mkdir();
        System.out.println("2.是否存在目录"+file.exists());
    }
}

在这里插入图片描述

创建多级目录,mkdir()无法完成,需要利用mkdirs()方法

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

public class Test09 {
    public static void main(String[] args) throws IOException {
        File file=new File("F:\\Test_2_4\\Test01\\Test002\\a\\b\\c");
        System.out.println("1.是否存在目录"+file.exists());
        file.mkdirs();
        System.out.println("2.是否存在目录"+file.exists());
    }
}

在这里插入图片描述

6.文件重命名、文件切换路径:renameTo()

文件剪切:只需要修改文件路径(修改文件的属性),开销小;
文件复制粘贴:需要读取文件,拷贝内容,粘贴内容,整个开销比较大。

//1.文件改名
import java.io.File;

public class Test10 {
    public static void main(String[] args) throws InterruptedException {
        File file=new File("F:\\Test_2_4\\Test01\\Test002\\b");
        File file2=new File("F:\\Test_2_4\\Test01\\Test002\\a");
        System.out.println("1.文件名字"+file.getAbsolutePath());
        file.renameTo(file2);
    }
}

修改之前:在这里插入图片描述
修改之后:在这里插入图片描述

//2.切换目录
import java.io.File;

public class Test11 {
    public static void main(String[] args) {
        File file=new File("F:\\Test_2_4\\Test02\\test01\\temp.doc");
        File file2=new File("F:\\Test_2_4\\Test02\\temp.doc");
        //切换目录
        file.renameTo(file2);
    }
}

切换前:
在这里插入图片描述
在这里插入图片描述

切换后
在这里插入图片描述
在这里插入图片描述

二、文件的读写

读、写文件–流
1.字节流(以字节流的形式去读写文件)

文件读取:Java标准库提供了InputStream(抽象类),实现类:FileInputStream。
往文件中写:OutputStream,实现类:FileOutputStream。

2.抽象类abstract修饰的类

主要特点是:
1.不能被实例化;
2.抽象方法必须放在抽象类当中;
3.抽象类既可以包含抽象方法也可以包含非抽象方法;
4.抽象类中的抽象方法没有具体的方法体。
如何使用抽象方法?
写一个子类继承抽象类,重写抽象方法。
如果需要设计一个类不能被实例化,就需要将这个类用abstract修饰。

3.接口

主要特点:
1.接口中方法的默认修饰符是:public abstract
2.接口中变量的默认修饰符是:public static int
3.接口中方法是没有方法体的。

4.接口、抽象类

1.一个普通成员(非静态成员)能否在抽象类中存在?能否在接口中存在?
一个普通普通的成员可以在抽象类中存在,
也不能在接口中存在,因为接口中的成员默认修饰符是public static final。
2.一个普通的方法(非抽象方法)能否在抽象类中存在?能否在接口中存在?
一个普通的方法可以在抽象类中存在,不可以在接口中存在,接口中的方法默认修饰符是public abstract。
3.一个抽象方法,能否在抽象类中存在?能否在接口中存在?
抽象方法必须在抽象类中存在,可以在接口中存在,接口中方法的默认修饰符是:public abstract。
4.一个类,能否继承多个抽象类?
不可以,一个类只能有一个父类,不允许多继承。
5.一个类,能否实现多个接口?
可以,一个类可以实现多个接口。

5.读文件:read()–>返回值类型:int
a. read():无参数,代表按照单个字节来读取文件,返回值是-1,代表读取完毕

import java.io.*;
//读取文件中的内容
public class Test02 {
    public static void main(String[] args) {
        InputStream inputStream=null;
        try {
            inputStream=new FileInputStream("F:\\Test_2_4\\demo03.txt");
            while(true){
                int ret=inputStream.read();
                if(ret==-1){
                    System.out.println("读取完毕");
                    break;
                }
                System.out.printf("%c",ret);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

代码结果图:
在这里插入图片描述

b. read(byte[] b):带有一个参数,以字节数组读取文件

下面举例:一次读取1024个字节,与一次读取一个字节相比:
减少了读取文件的次数,加大了执行效率,读文件的操作是十分缓慢的。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test04 {
    public static void main(String[] args) {
        try(InputStream inputStream=new FileInputStream("F:\\Test_2_4\\demo03.txt")){
            byte[] bytes=new byte[1024];
            while (true){
            //每次读取1024个字节
                int ret=inputStream.read(bytes);
                if(ret==-1){
                    System.out.println("读取结束");
                    break;
                }
                for (int i=0;i<bytes.length;i++){
                    System.out.printf("%c",bytes[i]);
                }
            }
        }catch(IOException e){
            e.printStackTrace();
        }
    }
}

结果展示:
在这里插入图片描述

c.如果文件当中有中文,该如何去读取呢?

中文和英文编码方式是不一样的,
中文采取的编码方式是uft-8或者是gbk
英文采取的编码方式是ascii
上面代码中打印,‘%c’,采用的编码方式是ascii,如果文件中存在中文,在打印的时候,会出现乱码的情况。
如何解决这种问题呢?
引入了Java标准库中提出的内置字符集的方式Scanner
Scanner:不仅可以从控制台读取标准输入值还可以从文件中读取文件内容

//第一版本
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;

public class Test05 {
    public static void main(String[] args) {
      try(InputStream inputStream=new FileInputStream("F:\\Test_2_4\\demo03.txt")){
          Scanner scanner=new Scanner(inputStream,"UTF-8");
          while(scanner.hasNext()){
              String s=scanner.next();
              System.out.println(s);
          }
      }catch(IOException e){
          e.printStackTrace();
      }
    }
}
//第二版本:Scanner本身也有close操作
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;

public class Test05 {
    public static void main(String[] args) {
      try(InputStream inputStream=new FileInputStream("F:\\Test_2_4\\demo03.txt")){
      //Scanner里面也有close关闭,在这里,实际上关闭的是inputStream
          try(Scanner scanner=new Scanner(inputStream,"UTF-8")){
              while(scanner.hasNext()){
                  String s=scanner.next();
                  System.out.println(s);
              }   
          }
      }catch(IOException e){
          e.printStackTrace();
      }
    }
}

结果:
在这里插入图片描述

上面的代码针对Scanner来说,进行了关闭操作。但是在Scanner in=new Scanner(System.in)代码当中,对Scanner没有进行关闭,这是为什么呢?
System.in:标准输入,一般不关闭,在创建进程的时候,系统就会自动打开标准输入、标准输出、标准错误这三个文件,当销毁进程的时候,这三个文件也就被关闭了,一般不会手动关闭。

6.资源泄漏是什么?

操作系统中的资源都是有限的。资源会指内存,文件描述符表…
文件描述符表是什么?
在用户态每创建一个进程或者是一个线程的时候,对应的,在内核态中就会创建一个PCB,PCB的属性当中,有一个文件描述符表。
进程中每打开一个文件,就会产生一个文件描述符,就会把这个文件描述符添加到文件描述符表当中。当不使用文件的时候,未关闭文件,当文件越来越多,以致将整个文件描述符表都占满了之后,再打开新的文件,就会产生打开文件失败的情况。

7.往文件中写数据-OutputStream
a.刷新flush

刷新flush一般会用到什么样的场景下?
缓冲区实际上是一段内存空间,OutputStream自带一块缓冲区,是介于内存和磁盘之间,写数据一般会写在缓冲区当中,当缓冲区满了之后/手动调用刷新flush之后,会将缓冲区中的内容写到磁盘当中。

b.往文件中写数据

一旦按照OutputStream的方式打开文件,就会清空文件中的内容。

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test06 {
    public static void main(String[] args) {
        //按照OutputStream的方式打开一个文件,一般会将文件中的内容删除掉
        try(OutputStream outputStream=new FileOutputStream("F:\\Test_2_4\\demo03.txt")){
            //1.写一个字符
            outputStream.write('a');
            //2.写一个字符数组
            byte[] bytes=new byte[]{
                    (byte)'a',(byte)'b',(byte)'c',(byte)'d'
            };
            outputStream.write(bytes);
            //3.写一个字符串
            String s="明天,你好";
            outputStream.write(s.getBytes());
        }catch(IOException e){
            e.printStackTrace();
        }
    }
}

结果:
在这里插入图片描述

c.封装了一个类,主要完成往文件中填写数据PrintWrite

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;

public class Test07 {
    public static void main(String[] args) {
        try(OutputStream outputStream=new FileOutputStream("F:\\Test_2_4\\demo03.txt")){
            try(PrintWriter printWriter=new PrintWriter(outputStream)){
                printWriter.println("明天你好,hello");
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

三、拓展

1.查找文件,并且指定是否要删除文件

指定一个目录,扫描这个目录,找到文件名中包含了指定字符的文件,并提示用户是否要删除这个文件,根据用户的决定是否进行删除操作。

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Test10 {
    public static List<File> findFile(String path,String name){
        List<File> fileList=new ArrayList<>();
        File file=new File(path);
        File[] files=file.listFiles();
        for (File f:files){
            if(f.isFile()){
                fileList.add(f);
            }else if(f.isDirectory()){
                try {
                    String tempPath=f.getCanonicalPath();
                    findFile(tempPath,name);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return fileList;
    }
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        System.out.println("请输入指定目录");
        String path=in.next();
        File file=new File(path);
        if(!file.isDirectory()){
            System.out.println("输入文件路径错误,退出");
            return;
        }
        System.out.println("请输入要删除文件的文件名:");
        String name=in.next();
        List<File> list=findFile(path,name);
        for (File f:list){
            if (f.getName().contains(name)){
                System.out.println("是否要删除该文件:yes/no");
                String judge=in.next();
                if(judge.equals("yes")){
                    f.delete();
                    System.out.println("删除成功,退出");
                    return;
                }else{
                    System.out.println("不删除文件,退出");
                    return;
                }
            }
        }
        System.out.println("文件没有被找到");
    }
}

结果展示:
在这里插入图片描述
2.复制一个文件
启动程序之后,让用户输入一个文件的路径(绝对路径),要求这个文件是一个普通文件(不是目录),再指定一个目标路径,通过程序,将这个文件进行复制目标路径下。

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

public class Test11 {
    public static void main(String[] args) throws IOException {
        Scanner in=new Scanner(System.in);
        System.out.println("请输入一个文件的绝对路径");
        String path=in.next();
        File file=new File(path);
        if(!file.isFile()){
            System.out.println("输入内容有误,退出");
            return;
        }
        System.out.println("请输入复制的目的路径");
        String aimPath=in.next();
        File aimFile=new File(aimPath);
        if(aimFile.exists()){
            System.out.println("文件已经存在,退出");
            return;
        }
        if(!aimFile.getParentFile().exists()){
            System.out.println("文件目录不存在,创建文件目录");
            String tempPath=aimFile.getParentFile().getCanonicalPath();
            File tempFile=new File(tempPath);
            tempFile.mkdirs();
        }
        try(InputStream inputStream=new FileInputStream(path);
            OutputStream outputStream=new FileOutputStream(aimPath)){
            while(true){
                byte[] bytes=new byte[1024];
                int ret=inputStream.read(bytes);
                if(ret==-1){
                    break;
                }
                outputStream.write(bytes,0,ret);
            }
            outputStream.flush();
        }catch(IOException e){
            e.printStackTrace();
        }
        System.out.println("复制完成");
    }
}

结果:
在这里插入图片描述

通过这些文件操作,在指定目录中按照文件内容查找,看看是否包含匹配的结果

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

public class Test12 {
    public static void main(String[] args) throws IOException {
        Scanner in=new Scanner(System.in);
        System.out.println("请输入要查找的绝对路径");
        String srcPath=in.next();
        File srcFile=new File(srcPath);
        if(!srcFile.isDirectory()){
            System.out.println("输入有误,退出");
            return;
        }
        System.out.println("请输入要查找的内容");
        String srcFind=in.next();
        List<File> files=new ArrayList<>();
        findFile(srcPath,srcFind,files);
        for (File f:files){
            System.out.println(f.getCanonicalFile());
        }
        if(files.size()==0){
            System.out.println("没有找到要查找的内容");
        }
    }
    public static void findFile(String srcPath,String srcFind,List<File> files) throws IOException {
        File srcFile=new File(srcPath);
        //获取该目录下的所有文件、目录
        File[] tempFile=srcFile.listFiles();
        for (File f:tempFile){
            if(f.isDirectory()){
                //如果是目录,就递归调用
                findFile(f.getCanonicalPath(),srcFind,files);
            }else if(f.isFile()){
                if(containsContent(f.getCanonicalPath(),srcFind)){
                    files.add(f);
                }
            }
        }
    }
    public static boolean containsContent(String path,String srcFind){
        StringBuilder stringBuilder=new StringBuilder();
        try(InputStream inputStream=new FileInputStream(path)) {
            Scanner scanner=new Scanner(inputStream,"UTF-8");
            while (scanner.hasNextLine()){
                String temp=scanner.nextLine();
                stringBuilder.append(temp);
            }
        }  catch (IOException e) {
            e.printStackTrace();
        }
        return stringBuilder.indexOf(srcFind)!=-1;
    }
}

结果:在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值