• 文件操作 IO


    文件(File)

    狭义的文件: 指的是硬盘上的文件和目录
    广义的文件: 泛指计算机中很多软硬件资源(操作系统中把很多硬件和软件资源抽象成了文件, 按照文件的方式同意管理)

    本章内容只讨论狭义的文件

    路径

    1. 绝对路径: 以c: , d: 盘符开头的路径
    2. 相对路径: 以当前所在的目录为基准(工作目录), 以. 或 … 开头(有时 . 可以省略), 找到指定的路径

    那么我们的IDEA的工作路径在哪呢?
    IDEA 的工作路径默认就是在当前的项目所在目录
    在这里插入图片描述

    Java 对于文件的操作

    1. 针对文件系统操作(文件的创建, 删除, 重命名)
    2. 针对文件内容的操作(文件的读和写)

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

    在这里插入图片描述
    parent 表示当前文件所在目录
    child 表示自身的文件名

            File file = new File("d:/text.txt");
    
    • 1

    构建一个File 对象

    import java.io.File;
    import java.io.IOException;
    
    public class IODemo1 {
        public static void main(String[] args) throws IOException {
            File file = new File("./test1.txt");
            // 获取文件名
            System.out.println(file.getName());
    
            // 获取父级路径
            System.out.println(file.getParent());
    
            // 获取完整路径
            System.out.println(file.getPath());
    
            // 获取绝对路径
            System.out.println(file.getAbsoluteFile());
    
            // 获取绝对路径的简化路径
            System.out.println(file.getCanonicalPath());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    判断文件

    import java.io.File;
    
    public class IODemo2 {
       public static void main(String[] args) {
           File file = new File("d:/f1/f2/test1.txt");
           // 这个文件是否存在
           System.out.println(file.exists());
    
           // 这是不是一个文件
           System.out.println(file.isFile());
    
           // 这是一个目录吗
           System.out.println(file.isDirectory());
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    创建文件

    import java.io.File;
    import java.io.IOException;
    
    public class ThreadDemo3 {
        public static void main(String[] args) throws IOException {
            File file = new File("./test.txt");
            //创建这个文件
            file.createNewFile();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    删除文件

    import java.io.File;
    
    public class IODemo4 {
        public static void main(String[] args) {
            File file = new File("./test.txt");
            // 删除文件
            file.delete();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    deleteOnExit

    
    import java.io.File;
    import java.io.IOException;
    
    public class IODemo5 {
        public static void main(String[] args) throws IOException {
            File file = new File("test.txt");
            System.out.println(file.exists());
            System.out.println(file.createNewFile());
            System.out.println(file.exists());
            //程序运行结束后删除
            file.deleteOnExit();
            System.out.println(file.exists());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    目录的创建

    import java.io.File;
    
    public class IODemo6 {
        public static void main(String[] args) {
            File dir = new File("d:/f1/f2/f3/f3");
            dir.mkdir();   // 只能创建一级目录
            dir.mkdirs();  // 创建多级目录
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    文件的重命名

    import java.io.File;
    
    public class IODemo7 {
        public static void main(String[] args) {
            File file = new File("./aaa/bbb/test.txt");
            File file1 = new File("./aaa/bbb/test2.txt");
            file.renameTo(file1);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Java 标准库的流对象

    从类型上分成两个大类

    1. 字节流: 操作二进制数据的
    2. 字符流: 操作文本数据

    在这里插入图片描述
    read 无参数版本:一次只读一个字节
    read 有一个参数版本: 把读到的内容填充到参数的这个字节数组中, (此处的参数是一个输出型参数), 返回值是实际读取的字节数
    read 有三个参数的版本: 和一个参数的差不多. 只不过是往数组的一部分区间里尽可能填充

    思考:

    read 读取的是一个字节, 按理说应该返回一个 byte , 但是实际上是返回int, 这是为什么呢?
    这里除了表示byte里的0~255 (-128 ~ 127) 这样的情况外, 还需要表示一个特殊情况, -1,这个标记表示读取文件结束了(读到末尾了).

    UTF-8 每个汉字三个字节

    字节流读取:

    import java.io.*;
    
    public class IODemo8 {
        // 使用字节流读取文件
        public static void main(String[] args) throws IOException {
            // 创建InputStream 对象的时候, 使用绝对路径或者相对路径都行, 也可以使用File对象
            InputStream inputStream = new FileInputStream("d:/test.txt");
    
    //        //进行读操作
    //        while (true) {
    //            int b = inputStream.read();
    //            if(b == -1) {
    //                // 读取完毕
    //                break;
    //            }
    //            //System.out.println(""+ (byte)b);
    //            System.out.printf("%x",(byte)b);
    //        }
    
                while (true) {
                    byte[] buffer = new byte[1024];
                    int len = inputStream.read(buffer);
                    System.out.println("len: "+ len);
                    if (len == -1) {
                        break;
                    }
                    // 此时读取的字符就被放到了byte[] 中了.
                    for (int i = 0; i < len; i++) {
                        System.out.printf("%x\n", (byte)buffer[i]);
                    }
                }
    
                inputStream.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    buffer 存在的意义,是为了提高 IO 操作的效率,
    单次 IO 操作, 是要访问硬盘的, 所以就会比较耗费时间,
    缩短了 IO 操作的次数, 所以效率也就提高了

    字节流写文件
    在这里插入图片描述
    也是类似的三个方法

    public class IODemo9 {
        // 进行写文件
        public static void main(String[] args) throws IOException {
            OutputStream outputStream = new FileOutputStream("d:/test.txt");
            outputStream.write(97);
            outputStream.write(98);
            outputStream.write(99);
            outputStream.write(100);
            outputStream.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述
    更推荐的写法
    这个写法虽然没有显示的写 close , 但是在 try 语句执行完的时候, 会自动执行到 close

    public class IODemo {
        public static void main(String[] args) throws IOException {
            try (OutputStream outputStream = new FileOutputStream("d:/test.txt")) {
                outputStream.write(97);
                outputStream.write(97);
                outputStream.write(97);
                outputStream.write(97);
                outputStream.write(97);
                outputStream.write(97);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    字符流读文件

    package io;
    
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.Reader;
    
    public class IODemo10 {
        // 字符流的操作
        public static void main(String[] args) {
            try (Reader reader = new FileReader("d:/test.txt")) {
                while (true) {
                    int ch = reader.read();
                    if (ch == -1) {
                        break;
                    }
                    System.out.println("" + (char)ch);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    字符流写文件

    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.Writer;
    
    public class IODemo11 {
        // 字符流写文件
        public static void main(String[] args) {
            try (Writer writer = new FileWriter("d:/test.txt")) {
                writer.write("hello world");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    下面我们实现一个删除文件的小程序

    import java.io.File;
    import java.util.Scanner;
    
    public class IODemo12 {
        private static Scanner scanner = new Scanner(System.in);
        public static void main(String[] args) {
            // 让用户输入一个指定搜索的目录
            System.out.println("请输入一个要搜索的路径: ");
            String basePath = scanner.next();
    
            // 针对用户输入进行简单判定,
            File root = new File(basePath);
            if (!root.isDirectory()) {
                // 路径不存在, 或者是一个普通文件, 此时无法进行搜索
                System.out.println("输入的路径有误");
                return;
            }
    
            System.out.println("请输入要删除的文件名: ");
            // 此处使用 next, 不用 next.Line
            String nameToDelete = scanner.next();
    
            // 针对指定路径进行扫描, 递归操作
            // 先从根目录出发(root)
            // 先看看这个目录是否有我们要删除的文件, 如果有就删除, 否则下一个
            // 如果是包含了一些目录, 那就进行递归
    
            scanDir(root,nameToDelete);
        }
    
        private static void scanDir(File root, String nameToDelete) {
            // 1. 先列出当前路径下包含和目录
            File[] files = root.listFiles();
            if (files == null) {
                // 当前目录没东西, 进行下一步递归
                return;
            }
            // 遍历当前列出的结果
            for (File f: files) {
                if (f.isDirectory()) {
                    // 如果是目录就进一步递归
                    scanDir(f,nameToDelete);
                } else {
                    // 如果是文件就判断
                    if (f.getName().contains(nameToDelete)) {
                        System.out.println("确认要删除 " + f.getName() + "吗?");
                    String choice = scanner.next();
                       if (choice.equals("Y") || choice.equals("y")) {
                            f.delete();
                           System.out.println("删除成功");
                       } else {
                           System.out.println("删除取消");
                       }
                    }
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    文件的复制
    就是把一个文件按照字节一次读取, 把结果写入另一个文件中

    import java.io.*;
    import java.util.Scanner;
    
    // 文件的拷贝
    public class IODemo13 {
        public static void main(String[] args) throws RuntimeException {
            // 输入两个路径 一个源 一个目标路径 (从哪里拷贝到哪)
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入要拷贝哪个文件: ");
            String srePath = scanner.next();
            System.out.println("请输入要拷贝到哪个地方: ");
            String destPath = scanner.next();
    
            File srcFile = new File(srePath);
            if (!srcFile.isFile()) {
                System.out.println("您输入的源路径有误!");
                return;
            }
            File destFile = new File(destPath);
            if (destFile.isFile()) {
                // 如果已经存在不能拷贝
                System.out.println("您输入的目标路径有误: ");
                return;
            }
    
            // 进行拷贝操作
            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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
  • 相关阅读:
    Docker:开启访问端口 || IDEA开发工具快速部署到服务器
    【苹果群发】iMessage苹果推字符串访问权限,而我们在SSL推杆证书中的步骤相同
    Leetcode84(柱状图中最大的矩形)
    电感重要参数的理解
    YOLOv8 多种任务网络结构详细解析 | 目标检测、实例分割、人体关键点检测、图像分类
    链动2+1模式:裂变增长,轻松吸引百万用户
    如何在Spring Boot中如何返回InputStream时采用文件的模式呢?
    【Go】(1)go语言开发环境配置
    pytorch使用LSTMCell层定义LSTM网络结构
    java计算机毕业设计弹幕视频网站源码+系统+lw文档+mysql数据库+部署
  • 原文地址:https://blog.csdn.net/qq_43339789/article/details/133965417