【IO】文件操作基础知识

目录

1.文件的操作:

2.文件内容的读写—数据流:

3.文件操作练习:


1.文件的操作:

  1. 文件分为狭义上的文件和广义的文件。
  2. 狭义上的文件:存储在硬盘上的数据,以“文件”为单位进行组织。文件夹也叫做目录。
  3. 通过“路径”的概念来描述一个文件在电脑上的具体位置。路径分为绝对路径(每个 / 间隔的部分都是目录)和相对路径(需要有基准)。
  4. 相对路径中 ./表示当前目录(./qq/Bin/QQ.exe);使用 ../ 表示返回到上级目录
  5. I(input)O(output),输入和输出的方向是以CPU/内存为中心。输入就是将外部设备(键盘)的数据放到内存里。
  6. File类;注意:有File对象不代表有真实存在该对象。File类的构造方法常用File(路径),这里的路径可以是绝对路径还可以是相对路径。一个file对象就是一个文件或目录。
    File file = new File("..//helloworld.txt");//并不要求该文件真实存在
    返回值类型 方法签名 说明
    String getName() 返回File对象纯文件名称
    boolean isDirectory() 判断是不是目录
    boolean isFile() 判断是不是普通文件
    boolean createNewFile() 创建文件,成功后返回true
    boolean delete() 删除该文件,成功后返回true
    void deleteOnExit() 进程退出时才会删除文件
    boolean mkdir() 创建目录
    boolean mkdirs() 创建多级目录
    boolean renameTo() 重命名

2.文件内容的读写—数据流:

  1. 【IO】文件操作基础知识_第1张图片
  2. 【IO】文件操作基础知识_第2张图片
  3. 读操作:InputStream;从外部设备读取到内存上。
    //InputStream是一个抽象类,不具体,不能实例化,所以需要用到FileInputStream
    //下面这个过程就相当于打开文件!想要读写文件就需要打开文件~
    InputStream inputStream = new FileInputStream("hello.txt");
    返回值类型 方法签名 说明
    int read() 读取一个字节的数据,返回-1代表读完了
    int read(byte[ ] b) 读取b.length字节数据放到b中,返回读到的数量,-1代表已经读完了
    int read(byte[ ] b, int m, int n) 读取n-m个字节到b中
    void close() 关闭字节流
  4. //1.读操作:无
    public static void main(String[] args) throws IOException {
            InputStream inputStream = new FileInputStream("hello.txt");
            while(true){
                int ret = inputStream.read();
                if(ret == -1){
                    break;
                }
                System.out.println(ret);
            }
            inputStream.close();
    }
    //2.读操作:使用Scanner来读数据
    public static void main(String[] args) throws IOException {
            InputStream inputStream = new FileInputStream("./hello.txt");
            //scanner搭配inputStream使用,读操作
            Scanner scanner = new Scanner(inputStream);
    
            while(scanner.hasNext()){
                System.out.println(scanner.next());
            }
    
            inputStream.close();
    }
    //3.读操作:使用byte数组
    public static void main(String[] args) throws IOException {
            try(InputStream inputStream = new FileInputStream("hello.txt")){
                byte[] ret = new byte[1024];
                int len = 0;
                while(true){
                     len = inputStream.read(ret);
                    if(len == -1){
                        break;
                    }
                    for (int i = 0; i < len; i++) {
                        System.out.println(ret[i]);
                    }
                }
            }
    }
    //4.读操作:使用try和scanner
    public static void main(String[] args) throws IOException {
            try(InputStream inputStream = new FileInputStream("./hello.txt");
                  Scanner scanner = new Scanner(inputStream)){
                while(scanner.hasNext()){
                    String ret = scanner.next();
                    System.out.println(ret);
                }
            }
    }
  5. 写:OutputStream;
    //OutputStream是一个抽象类,不具体,不能实例化,所以需要用到FileOutputStream
    //使用OutputStream写文件的时候,只要文件打开成功,就会把文件原来的内容清空
    OutputStream outputStream = new FileOutrputStream("./hello.txt");
    返回值类型 方法签名 说明
    void write(int b) 写入一个字符将b这个字符数组中的数据全部写入
    void write(byte[ ] b) 将b这个字符数组中的数据全部写入
    int write(byte[ ] b, int m, int n) 将b这个字符数组中的数据从m开始写入
    void close() 关闭字节流
    void flush() 刷新缓冲区
  6. //1.写操作
    public static void main(String[] args) throws IOException {
            OutputStream outputStream = new FileOutputStream("./hello.txt");
            //打开文件后,会先把文件内容清空
            outputStream.write(97);
            outputStream.write(98);
            outputStream.write(99);
    
            outputStream.close();
    }
    //2.写操作:使用PrintWriter来写操作
    public static void main(String[] args) throws IOException {
            OutputStream outputStream = new FileOutputStream("./hello.txt");
    
            PrintWriter writer = new PrintWriter(outputStream);
    
            writer.print(45);
            writer.print('c');
            writer.println();
    
            //一定要刷新缓冲区
            outputStream.flush();
    
            //一定要关闭文件,writer.close()!!!
            writer.close();
    }
    //3.写操作:使用try和PrintWriter来写操作
    public static void main(String[] args) throws IOException {
            try(OutputStream outputStream = new FileOutputStream("./hello.txt");
                PrintWriter writer = new PrintWriter(outputStream)){
    
                writer.println();
                writer.print('s');
    
                writer.flush();
            }
    }
    //4.写操作:使用OutputStreamWriter和PrintWriter来写
    public static void main(String[] args) throws IOException {
            try(OutputStream outputStream = new FileOutputStream("./hello.txt");
                OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
                PrintWriter printWriter = new PrintWriter(outputStreamWriter)){
                
                printWriter.println();
                printWriter.print(1);
                printWriter.print(12);
                printWriter.print(13);
    
                printWriter.flush();
            }
    }
  7. 刷新缓冲区:OutputStream为了减少设备操作的次数,写数据时会将数据暂时写入缓冲区中,直到满足条件才写到内存上。因此为了保证数据不会遗留在缓冲区上,我们需要用到刷新缓存区flash()的操作来将数据刷到设备上。 

  8. 文件内容操作后一定要将文件close,否则会造成文件资源泄露,类比于图书馆借书(一伙人直只借不还,图书馆的书不就越来越少了嘛~)。

    为什么需要close文件???
    1.每个进程都对应着PCB,PCB里面有一个字段,文件描述符表
    2.同一个进程里面多个PCB可能同时使用一份文件描述符表
    3.文件描述符表相当于一个数组,每次打开一个文件,都会在表里创建一个项
    4.如果关闭则会把对应的项给释放掉
    5.如果不关闭,意味着这个项一直占着位置,
    6.如果持续打开文件且从来不关就会导致表项(数组里的元素)被耗尽
    7.导致后续文件在打开文件就会打开失败
    8.所以需要保证代码执行完关闭文件

3.文件操作练习:

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

思路:

1.先让用户输入要扫描的路径和要查找的字
2.遍历目录,找到名字包含的的文件
3.询问用户是否删除

代码:

//扫描目录,找到包含指定字符的所有普通文件,找到后询问是否要删除
public class Demo {
    public static void main(String[] args) throws IOException {
        //1.让用户输入必要的信息
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要扫描的路径:");
        File rootDir = new File(scanner.next());
        if(!rootDir.isFile()){
            System.out.println("输入的目录有错误!!!");
            return;
        }
        System.out.println("请输入要查找的关键字:");
        String toDelete = scanner.next();


        //2.遍历目录
        scanDir(rootDir,toDelete);

    }

    private static void scanDir(File rootDir, String toDelete) throws IOException {
        System.out.println("当前访问: "+rootDir.getCanonicalPath());
        File[] files = rootDir.listFiles();
        if(files == null){
            //说明目录是个空的目录
            return;
        }
        for (File f : files) {
            if(f.isDirectory()){
                scanDir(f,toDelete);
            }else{
                checkDelete(f,toDelete);
            }
        }
    }

    private static void checkDelete(File f, String toDelete) throws IOException {
        if(f.getName().contains(toDelete)){
            System.out.println("该单词"+toDelete+" 被 "+f.getCanonicalPath()+"包含了,是否要删除?(Y/N)" );
            Scanner scanner = new Scanner(System.in);
            String choice = scanner.next();
            if(choice.equals("Y") || choice.equals("y")){
                f.delete();
            }
        }
    }
}

2.将普通的文件复制一份

思路:

把第一个文件打开,将里面的内容逐个字节的读取出来,写入到第二个文件中

代码:

//普通文件的复制
public class Demo {
    public static void main(String[] args) throws IOException {
        //1.输入
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要复制的源文件:");
        File srcFile = new File(scanner.next());

        System.out.println("请输入目标文件:");
        File destFile = new File(scanner.next());

        if(!srcFile.isFile()){
            System.out.println("输入的源文件有错误!!!");
            return;
        }
        if(!destFile.getParentFile().isDirectory()){
            System.out.println("输入的目标文件有误!!!");
            return;
        }

        //2.打开目标文件,按照字节读取写入到目标文件中

        try(InputStream inputStream = new FileInputStream(srcFile);
            OutputStream outputStream = new FileOutputStream(destFile)){
            while(true){
                int ret = inputStream.read();
                if(ret == -1){
                    break;
                }
                outputStream.write(ret);
            }
        }

    }
}

3.扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)

思路:

1.先让用户输入要扫描的路径和要查找的字
2.遍历目录,找到名字和内容都包含的文件
3.询问用户是否删除

代码:

//扫描文件,判断其中是否包含关键字
public class Demo {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要扫描的路径:");
        File rootDir = new File(scanner.next());

        if(!rootDir.isFile()){
            System.out.println("输入的路径有问题!");
            return;
        }
        System.out.println("请输入要搜索的关键字:");
        String toFind = scanner.next();

        //2.遍历
        scanDir(rootDir,toFind);
    }

    private static void scanDir(File rootDir, String toFind) throws IOException {
        System.out.println("当前路径:"+rootDir.getCanonicalPath());
        File[] files = rootDir.listFiles();
        if(files == null){
            return;
        }
        for(File f : files){
            if(f.isDirectory()){
                scanDir(f,toFind);
            }else{
                checkDelete(f,toFind);
            }
        }

    }

    private static void checkDelete(File f, String toFind) throws IOException {
        //先检查文件名
        if(f.getName().contains(toFind)){
            System.out.println(f.getCanonicalPath() + "文件名中包含 " + toFind+" 是否删除(Y/N)");
        }
        try(InputStream inputStream = new FileInputStream(f)){
            StringBuilder sb = new StringBuilder();
            Scanner scanner = new Scanner(inputStream);

            while(scanner.hasNextLine()){
                sb.append(scanner.nextLine() + "\n");
            }
            if(sb.indexOf(toFind) > -1){
                System.out.println(f.getCanonicalPath() + "文件内容中包含 " + toFind+" 是否删除(Y/N)");

            }
        }
    }
}

如果对您有帮助的话,

不要忘记点赞+关注哦,蟹蟹

如果对您有帮助的话,

不要忘记点赞+关注哦,蟹蟹

如果对您有帮助的话,

不要忘记点赞+关注哦,蟹蟹

你可能感兴趣的:(windows,java,服务器)