• 2023.9.26 IO 文件操作详解


    目录

    文件

            文件路径

            文件类型

    Java 文件操作 

    文件系统操作

    文件内容操作

    字节流

    InputStream

    OutputStream

    字符流

    Reader

    Writer

    补充 

    close 的必要性

    Scanner 的基本了解


    文件

    • 当前指硬盘上的文件和文件夹
    • 相对于 变量 在内存中,文件 则是在硬盘上

    文件路径

    • 每个文件在硬盘上均有一个具体的路径
    实例:

    注意:
    • 正斜杠 " / " 和 反斜杠 " \ " 均可以用来表示路径 
    • 推荐优先使用正斜杠 " / "
    • 当在代码中写文件路径时,使用反斜杠 " \ " 可能会导致 文件路径 部分变为 转义字符 的现象

    两种路径表示

    • 绝对路径:以 盘符 开头的路径
    • 相对路径:以当前所在的目录(工作目录)为基准,以 . 或者 .. 开头,来找到指定路径( . 有时候可省略)
    实例:

    • IDEA 的工作路径默认为当前项目所在目录

    文件类型

    • word、exe、图片、视频、音频、源代码、动态库 ......

    文本文件

    • 存 文本 和 字符串
    • 字符串 由 字符 构成,每个字符均通过一个数字表示,该文本文件中存的数据,必须是指定字符编码的码表内的数据

    二进制文件

    • 存二进制数据数据,可存储任何数据,无文本文件的限制!
    区分文件:
    • 使用 记事本 打开该文件
    • 记事本 出现乱码,则为 二进制文件
    • 记事本 无乱码,则为 文本文件

    Java 文件操作 

    文件系统操作

    • 文件的创建、删除、重命名......
    File 中的静态变量
    pathSeparator由系统决定 代指 " / " 或 " \ " 
    File 中的构造方法
    File(File parent, Sting child)根据 父目录 + 孩子文件路径,创建 File 实例(可为绝对路径或相对路径)
    File(String parent, Sting child)根据 父目录路径 + 孩子文件路径,创建 File 实例(可为绝对路径或相对路径)
    File(File pathname)根据 文件路径创建一个 File 实例,路径可以是绝对路径或相对路径
    • 通常使用红色标注的构造方法


    File 中的常见方法

    1. package io;
    2. import java.io.File;
    3. import java.io.IOException;
    4. public class IODemo1 {
    5. public static void main(String[] args) throws IOException {
    6. // 这里随便创建一个 File对象
    7. File file = new File("./test.txt");//File() 中的路径不要求真实存在
    8. // 打印 file 的文件名
    9. System.out.println(file.getName());
    10. // 打印 file 的父级路径
    11. System.out.println(file.getParent());
    12. // 打印 file 的完整路径
    13. System.out.println(file.getPath());
    14. // 打印 file 的绝对路径
    15. System.out.println(file.getAbsolutePath());
    16. // 打印 file 绝对路径的简化路径
    17. System.out.println(file.getCanonicalPath());
    18. }
    19. }

    运行结果:


     
    1. package io;
    2. import java.io.File;
    3. import java.io.IOException;
    4. public class IODemo2 {
    5. public static void main(String[] args) throws IOException {
    6. // 这里创建一个 File对象
    7. File file = new File("./test.txt");//File() 中的路径不要求真实存在
    8. // file对象在真实的硬盘路径上并不存在,从而可以通过该方法根据file的路径创建一个新文件
    9. file.createNewFile();
    10. // 打印 file 是否存在
    11. System.out.println(file.exists());
    12. // 打印 file 是否为普通文件
    13. System.out.println(file.isFile());
    14. // 打印 file 是否为目录
    15. System.out.println(file.isDirectory());
    16. }
    17. }

    运行结果:


    1. package io;
    2. import java.io.File;
    3. public class IODemo3 {
    4. public static void main(String[] args) {
    5. // 这里创建一个 File对象
    6. File file = new File("./test.txt");//File() 中的路径不要求真实存在
    7. // 将文件从硬盘中删除
    8. file.delete();
    9. // 根据 File 对象,标注文件将被删除,删除动作会到 JVM 运行结束时才会进行
    10. // 也就是该删除 是在程序退出的时候自动删除,比如程序中需要使用到一些 "临时文件" 的时候,会用到
    11. // file.deleteOnExit();
    12. }
    13. }

    运行结果:


    1. package io;
    2. import java.io.File;
    3. public class IODemo4 {
    4. public static void main(String[] args) {
    5. // 这里创建一个 File对象
    6. File dir1 = new File("./test1");//File() 中的路径不要求真实存在
    7. // 根据 dir路径 创建一个目录,仅能创建一级目录
    8. dir1.mkdir();
    9. // 这里创建一个 File对象
    10. File dir2 = new File("./test2/aaa/bbb");//File() 中的路径不要求真实存在
    11. // 根据 dir路径 创建一个目录,可创建多级目录
    12. dir2.mkdirs();
    13. }
    14. }

    运行结果:


    1. package io;
    2. import java.io.File;
    3. public class IODemo5 {
    4. public static void main(String[] args) {
    5. // 这里创建一个 File对象
    6. File file = new File("./test2");
    7. File test = new File("./test333");
    8. // 使用该方法对 file 进行重命名
    9. file.renameTo(test);
    10. }
    11. }

    运行结果:


    文件内容操作

    • 就是文件的读和写
    • InputStream 、 Reader、OutputStream 、 Writer 均为抽象类不能直接 new

    四大操作

    • 打开文件(构造对象)
    • 关闭文件(close)
    • 读文件(InputStream 和 Reader)
    • 写文件(OutputStream 和 Writer)

    字节流

    • 操作二进制数据
    InputStream
    1. package io;
    2. import java.io.FileInputStream;
    3. import java.io.FileNotFoundException;
    4. import java.io.IOException;
    5. import java.io.InputStream;
    6. public class IODemo6 {
    7. public static void main(String[] args) throws IOException {
    8. // 创建 InputStream对象 时,使用绝对路径 或 相对路径 均可,也可使用 File对象
    9. // 此处的 InputStream 为抽象类,当我们创建对象时,需指定一个具体实现类
    10. // 此处我们关注文件的读取,从而使用 FileInputStream类
    11. InputStream inputStream = new FileInputStream("d:/test.txt");
    12. // 进行读操作
    13. while (true) {
    14. // read方法 无参数,一次读一个字节
    15. // read方法 一个参数,把读到的内容填充到参数的字节数组中(此处的参数为输出型参数)返回值是实际读取的字节数
    16. // read方法 三个参数,往数组的一部分区间中尽可能填充
    17. // 此处 read方法读取一个字节,按照道理应该返回 byte类型,但是 read方法 却返回 int类型
    18. // 因为除了返回 byte中所表示的 00000000~11111111 这些情况外,还需要有读取文件结束的标志
    19. // 从而这里使用 -1 来表示读到文件末尾,从而使用 int类型 来返回
    20. int b = inputStream.read();
    21. if (b == -1) {
    22. // 读取完毕
    23. break;
    24. }
    25. // 此处使用 16进制将每个字节打印出来
    26. System.out.printf("%x\n",(byte)b);
    27. }
    28. // 最后需关闭文件
    29. inputStream.close();
    30. }
    31. }

    运行结果:


    1. package io;
    2. import java.io.FileInputStream;
    3. import java.io.IOException;
    4. import java.io.InputStream;
    5. public class IODemo7 {
    6. public static void main(String[] args) throws IOException {
    7. InputStream inputStream = new FileInputStream("d:/test.txt");
    8. // 进行读操作
    9. while (true) {
    10. // read方法 无参数,一次读一个字节
    11. // read方法 一个参数,把读到的内容填充到参数的字节数组中(此处的参数为输出型参数)返回值是实际读取的字节数
    12. // read方法 三个参数,往数组的一部分区间中尽可能填充
    13. // 即先准备好一个数组
    14. byte[] buffer = new byte[1024];
    15. // 正因为往 read方法中传入 buffer 这个参数,所以才能让 read方法内部针对 buffer数组进行填写,从而此处的参数为 输出型参数
    16. // 这里与之前Java一般传参场景是不同的,习惯的是将输入的信息作为参数,输出的信息作为返回值
    17. // 而此处是使用参数来返回内容
    18. int len = inputStream.read(buffer);
    19. // 虽然 buffer数组 的长度为1024,但当实际上文件的长度是有限的,如果剩余长度超过1024,此时 1024个字节都会填满,则返回值len为1024
    20. // 但是如果当前剩余长度不足1024,此时有多少 read方法就往 buffer数组中填多少,则返回值len 为实际读取的长度
    21. // 当然如果读完了,此时 read方法 继续读,但读不到一个字节,则返回值len为-1,表示文件已经读完了!
    22. System.out.println("len:" + len);
    23. if (len == -1) {
    24. // 读取完毕
    25. break;
    26. }
    27. // 此处使用 16进制将每个字节打印出来
    28. for (int i = 0; i < len; i++) {
    29. System.out.printf("%x\n",buffer[i]);
    30. }
    31. }
    32. // 最后需关闭文件
    33. inputStream.close();
    34. }
    35. }

    运行结果:

    注意:

    • buffer 译为缓冲区,其存在的目的就是为了提高 IO操作 的效率
    • 单次 IO操作,是要访问 硬盘 / IO设备 ,单次操作比较耗时间的且时长固定,频繁进行 IO操作,其总耗时也相应增加
    • 从而减少 IO操作 的次数,便可以提高程序整体的效率
    • 从而引入 buffer 使 read方法 一次读多个字节,便有效降低了循环次数,也就是IO操作的次数

    OutputStream
    1. package io;
    2. import java.io.FileNotFoundException;
    3. import java.io.FileOutputStream;
    4. import java.io.IOException;
    5. import java.io.OutputStream;
    6. public class IODemo8 {
    7. // 进行写文件
    8. public static void main(String[] args) throws IOException {
    9. try(OutputStream outputStream = new FileOutputStream("d:/test.txt")) {
    10. // 默认情况下,outputStream 打开一个文件,会先清空文件原有的内容
    11. outputStream.write(97);
    12. outputStream.write(98);
    13. outputStream.write(99);
    14. outputStream.write(100);
    15. }
    16. // 关闭文件
    17. // outputStream.close(); 该行代码由 try语句块 自动实现
    18. // 上述代码加入 try语句块 的目的就是为了能够确保 文件的关闭,也就是 close() 方法的执行
    19. // 之所以无显示的写 close() 方法,是因为该 try语句块 在 JAVA 中称为 try with resources 语法
    20. // 该语法只要 try语句块 执行完毕,就可以自动执行到 close() 方法
    21. }
    22. }

    运行结果:

    字符流

    • 操作文本数据

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

    运行结果:


    Writer
    1. package io;
    2. import java.io.FileWriter;
    3. import java.io.IOException;
    4. import java.io.Writer;
    5. public class IODemo10 {
    6. public static void main(String[] args) throws IOException {
    7. try (Writer writer = new FileWriter("d:/test.txt")){
    8. // 默认情况下,writer 打开一个文件,会先清空文件原有的内容
    9. writer.write("hello world");
    10. // 像这样的写操作,其实是先写到缓冲区中,自己代码可有缓冲区、标准库有缓冲区、操作系统内核有缓冲区 等
    11. // 当写操作执行完了,内容可能在缓冲区中,还未真正进入硬盘
    12. // 此时 close 操作就会触发缓冲区的冲刷操作(将缓冲区中的内容写到硬盘中)
    13. // 当然使用 close 后文件将会直接关闭,从而无法继续对文件进行操作
    14. // 使用 flush 可以手动冲刷缓冲区,且还能继续对文件进行操作
    15. // 手动冲刷缓冲区
    16. writer.flush();
    17. }
    18. }
    19. }

    运行结果:

    补充 

    close 的必要性


    Scanner 的基本了解

    1. package io;
    2. import java.io.FileInputStream;
    3. import java.io.FileNotFoundException;
    4. import java.io.IOException;
    5. import java.io.InputStream;
    6. import java.util.Scanner;
    7. public class IODemo11 {
    8. public static void main(String[] args) {
    9. // 这里的 System.in 是一个输入流对象,指向标准输入
    10. // 从而这里的 scanner 便从键盘读取
    11. // Scanner scanner = new Scanner(System.in);
    12. // 当然我们也可以在 使 scanner 读取文件,仅需更换传入的流对象,传入文件流对象即可
    13. try (InputStream inputStream = new FileInputStream("d:/test.txt") ){
    14. Scanner scanner = new Scanner(inputStream);
    15. // 此时这里的 scanner 就是从 文件 进行读取
    16. scanner.next();
    17. } catch (IOException e) {
    18. e.printStackTrace();
    19. }
    20. // 注意实际上 scanner 的 close 本质上是要关闭内部包含的这个流对象
    21. // 但是 其内部的 inputStream对象 已经被 try() 关闭了,从而在里面的 scanner 不关闭 也没关系
    22. }
    23. }
  • 相关阅读:
    BUUCTF 乌镇峰会种图 1
    1024快乐
    游戏物理引擎+特效系统
    SQLite去除.db-shm和.db-wal文件【已解决】
    java调用Excel中的GAMMADIST函数返回伽玛分布
    Java实现Modbus Tcp协议读写模拟工具数据
    (附源码)springboot教学评价 毕业设计 641310
    java jedis连接redis数据库实战
    设计模式系列-创建者模式
    【Linux】用户管理
  • 原文地址:https://blog.csdn.net/weixin_63888301/article/details/133497479