[Java EE] 文件操作(系统文件和字节流字符流)

一.文件操作

1.核心概念

文件 : 存储数据 ; 目录 : 存储文件/子目录的容器 ; Java 中均通过抽象类/接口表示

绝对路径 : 从根目录触发(如 D:/test/file.txt) ; 相对路径 : 从当前项目出发(如果再 IDEA 中直接运行 , 那么基准路径就是项目目录 ; 如果打了 jar 包 , 单独运行 jar 包 , 当前再哪个目录下执行运行命令的就是基准目录)

: 传统 IO 的核心 , 分为字节流(操作任意文件) 和 字符流(仅操作文本文件)

文本文件 : 数据以字符为基本 , 通过字符编码将字符映射为字节存储(能被记事本直接打开读懂) ; 二进制文件 : 以字节为单位 , 按一定格式存储(计算机可直接解析的原始字节流 , 用记事本打开为乱码)

2.Java 中操作系统文件

Java 中通过 java.io.file 类来对一个文件(包括目录)进行抽象描述 ;

注意 : 有 file 对象并不代表有真实文件存在

① 属性

|--------------------------|---------------------------------|--------------------------|
| 静态常量 | 作用 | 示例(Windows/Linux) |
| File.separator | 系统默认的「文件路径分隔符」 | Windows:\ Linux:/ |
| File.pathSeparator | 系统默认的「路径列表分隔符」(如环境变量 PATH) | Windows:; Linux:: |
| File.separatorChar | 字符类型的路径分隔符(同 separator) | Windows:'\'Linux:'/' |
| File.pathSeparatorChar | 字符类型的路径列表分隔符(同 pathSeparator) | Windows:';'Linux:':' |

java 复制代码
// 避免硬编码 "\\" 或 "/",用 separator 跨平台兼容
String path = "data" + File.separator + "test.txt"; 
System.out.println(path); 
// Windows 输出:data\test.txt;Linux 输出:data/test.txt

② 构造方法

|-------------------------------------|----------------------------------------|
| 方法名 | 说明 |
| File(File parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例 |
| File(String pathname) | 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径 |
| File(String parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示 |

③ 常用方法 (基础)

|---------|--------------------|-------------------------------------------------|
| 返回值 | 方法签名 | 说明 |
| String | getParent() | 返回 File 对象的父目录文件路径 |
| String | getName() | 返回 File 对象的纯文件名称 |
| String | getPath() | 返回 File 对象的文件路径(构造方法传入绝对 / 相对路径,此方法就返回对应路径) |
| String | getAbsolutePath() | 返回 File 对象的绝对路径(无论构造方法传相对 / 绝对路径,此方法都返回绝对路径) |
| String | getCanonicalPath() | 返回 File 对象的修饰过的绝对路径(简化路径,把.//../等符号替代为实际路径) |
| boolean | exists() | 判断 File 对象描述的文件是否真实存在 |
| boolean | isDirectory() | 判断 File 对象代表的文件是否是一个目录 |
| boolean | isFile() | 判断 File 对象代表的文件是否是一个普通文件 |

java 复制代码
import java.io.File;
import java.io.IOException;

public class demo1 {
    public static void main(String[] args) throws IOException {
        //File file = new File("D:/JavaCode/src/FIle/demo.txt");//绝对路径
        //File file1 = new File("D:/JavaCode/src/FIle", "demo.txt");
        //File parent = new File("D/JavaCode/src/FIle");new File(parent, "demo.txt");
        File file2 = new File("./demo.txt");//相对路径
        System.out.println(file2.getParent());
        System.out.println(file2.getName());
        System.out.println(file2.getPath());
        System.out.println(file2.getAbsoluteFile());
        System.out.println(file2.getCanonicalFile());
        System.out.println(file2.exists());
        System.out.println(file2.isDirectory());
        System.out.println(file2.isFile());
    }
}

④ 常用方法

|---------------|-------------------------|------------------------------------------------------|
| 修饰符及返回值类型 | 方法签名 | 说明(含手写补充) |
| boolean | createNewFile() | 根据 File 对象,自动创建一个空文件。成功创建后返回 true(注:需处理 IO 异常) |
| boolean | delete() | 根据 File 对象,删除该文件。成功删除后返回 true |
| void | deleteOnExit() | 根据 File 对象,标注文件将被删除,删除动作会到 JVM 运行结束时才会进行 |
| String[] | list() | 返回 File 对象代表的目录下的所有文件名 |
| File[] | listFiles() | 返回 File 对象代表的目录下的所有文件,以 File 对象表示(可以对 File 数组继续进行操作) |
| boolean | mkdir() | 创建 File 对象代表的目录(make directory) |
| boolean | mkdirs() | 创建 File 对象代表的目录,如果必要,会创建中间目录(创建多级目录) |
| boolean | renameTo(File dest) | 进行文件改名,也可以视为我们平时的剪切、粘贴操作 |
| boolean | canRead() | 判断用户是否对文件有可读权限 |
| boolean | canWrite() | 判断用户是否对文件有可写权限 |

示例 1 : file1.createNewFile();

java 复制代码
import java.io.File;
import java.io.IOException;

public class demo2 {
    public static void main(String[] args) throws InterruptedException {
        File file = new File("./demo3.java");
        file.deleteOnExit();
        Thread.sleep(1000);
    }
    public static void main1(String[] args) throws IOException {
        File file1 = new File("./text.txt");
        file1.createNewFile();
        System.out.println(file1.exists());
        System.out.println(file1.isFile());
        System.out.println(file1.isDirectory());
        //System.out.println(file1.delete());//若执行这行代码则文件消失
    }

示例 2 : 返回文件名

java 复制代码
import java.io.File;
import java.util.Arrays;

public class demo4 {
    public static void main(String[] args) {
        File file = new File("d:/");
        String[] list = file.list();
        System.out.println(Arrays.toString(list));
        File[] files = file.listFiles();
        System.out.println(Arrays.toString(files));
    }
}

示例 3 : 创建目录

java 复制代码
import java.io.File;

public class demo5 {
    public static void main(String[] args) {
        File file = new File("./test/1/2/3");
        Boolean a = file.mkdirs();
        System.out.println(a);//true,mkdirs() 能同时创建多级目录

        Boolean b = file.mkdir();
        System.out.println(b);//false,mkdir() 只能创建单级目录

    }
}

示例 4 : 剪切操作(需要执行上一个代码块)

java 复制代码
import java.io.File;

public class demo6 {
    public static void main(String[] args) {
        File file = new File("./test");
        File file2 = new File("./src/test");
        boolean a = file.renameTo(file2);
        System.out.println(a);
    }
}

3.文件内容操作 -- 数据流

Java 文件内容操作 , 核心基类是四个抽象类**(InputStream/OutputStream/Reader/Writer)**

基类 ,对应 4 个常用文件实现类(FileInputStream**/** FileOutputStream**/** FileReader**/** FileWriter) , 共八个核心类 , 覆盖二进制文件读写和文本文件读写的所有场景

|--------|-------------------|--------------------|----------------------|------------|
| 体系 | 抽象基类(2 个) | 文件实现类(2 个) | 核心用途 | 操作对象 |
| 字节流 | InputStream(读) | FileInputStream | 读取二进制文件(图片、视频、压缩包等) | 字节(byte) |
| 字节流 | OutputStream(写) | FileOutputStream | 写入二进制文件 | 字节(byte) |
| 字符流 | Reader(读) | FileReader | 读取文本文件(.txt/.java 等) | 字符(char) |
| 字符流 | Writer(写) | FileWriter | 写入文本文件 | 字符(char) |

4. 字节流 -- 操作二进制文件

4.1 抽象基类 InputStream (字节输入流)

InputStream 是所有字节输入流的父类 , 抽象类

核心方法 :

|-------------------------------------------|-----------------------------------|-----------------------------------|
| 方法签名 | 作用 | 备注 |
| int read() | 读 1 个字节,返回字节值(0~255);读到末尾返回 -1 | 单字节读取,效率低 |
| int read(byte[] buffer) | 读多个字节到缓冲区,返回实际读取的字节数;末尾返回 -1 | 推荐!批量读取,效率高 |
| int read(byte[] buffer,int off,int len) | 读 len个字节到缓冲区,从 off 下标开始存储 | 精细控制读取范围 |
| void close() | 关闭流,释放资源 | 必须调用(建议用 try-with-resources 自动关闭) |
| long skip(long n) | 跳过 n个字节不读 | 少用,适用于大文件跳转 |

4.2 文件实现类 FIleInputStream(文件字节输入流)

InputStream 的子类 , 专门用于从文件读取字节

构造方法 :

java 复制代码
// 1. 传入文件路径(字符串)
InputStream in = new FileInputStream("D:/test.jpg");
// 2. 传入 File 对象
File file = new File("D:/test.jpg");
InputStream in = new FileInputStream(file);

示例 1 : 将文件完全读的两种方式

java 复制代码
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class demo7 {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream("./test.txt");
            while(true){
                int data = inputStream.read();
                if(data == -1){
                    break;
                }
                System.out.printf("0x%x ",data);
            }
        }
        finally {
            inputStream.close();
        }

    }
}
java 复制代码
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class demo8 {
    public static void main(String[] args) throws IOException {

        try(InputStream inputStream = new FileInputStream("./test.txt")){
            //此处资源要求在try括号内直接声明并初始化, 并且使用括号将资源包裹起来, 避免出现异常时资源未关闭的情况
            while(true){
                byte[] data = new byte[1024];
                int n = inputStream.read(data);//返回读取的字节数
                System.out.println("n="+n);
                if(n == -1){
                    break;
                }
                for(int i = 0;i<n;i++){
                    System.out.print(data[i]+" ");
                }
                System.out.println();
            }
        }
    }
}

4.3 抽象基类 : OutputStream(字节输出流)

OutputStream 是所有字节输出流的父类 , 抽象类

核心方法 :

|-----------|-------------------------------------|---------------------------------------------------------------------------------|
| 返回值类型 | 方法签名 | 说明 |
| void | write(int b) | 写入要给字节的数据 |
| void | write(byte[] b) | 将 b 这个字节数组中的数据全部写入输出流中 |
| int | write(byte[] b, int off, int len) | 将 b 这个字节数组中从 off 开始的数据写入输出流中,一共写 len 个 |
| void | close() | 关闭字节流 |
| void | flush() | 重要:I/O 速度较慢,多数 OutputStream 会先将数据写入缓冲区以减少设备操作次数;调用此方法可将缓冲区中残留的数据刷入设备,避免数据丢失 |

4.4 文件实现类 : FileOutputStream(文件字节输出流)

FileOutputStream 是 OutputStream 子类 , 用于向文件写入字节

构造方法 :

java 复制代码
// 1. 覆盖写入(文件已存在则清空原有内容)
OutputStream out = new FileOutputStream("D:/test_copy.jpg");
// 2. 追加写入(文件已存在则在末尾添加内容)
OutputStream out = new FileOutputStream("D:/test_copy.jpg", true);
// 3. 传入 File 对象
File file = new File("D:/test_copy.jpg");
OutputStream out = new FileOutputStream(file, true);

示例 1 : 写入字节

java 复制代码
import java.io.*;

public class demo9 {
    public static void main(String[] args) throws IOException {
        try(OutputStream outputStream = new FileOutputStream("./test.txt")){//如果不加true将会覆盖原文件内容
            //此处需要处理两个异常
            byte[] data = {88,66,85};
            outputStream.write(data);
        }
    }
    public static void main1(String[] args) throws IOException {
        try(OutputStream outputStream = new FileOutputStream("./test.txt",true)){
            //此处需要处理两个异常
            outputStream.write(78);
            outputStream.write(99);
            outputStream.write(79);
        }
    }
}

5. 字符流 -- 操作文本文件

5.1 抽象基类 : Reader(字符输入流)

Reader 是所有字符输入流的父类 , 抽象类

核心方法 :

|-------------------------------------------|-----------------------------------|-----------|
| 方法签名 | 作用 | 备注 |
| int read() | 读 1 个字符,返回字符的 Unicode 码;末尾返回 -1 | 单字符读取,效率低 |
| int read(char[] cbuf) | 读多个字符到字符缓冲区,返回实际读取的字符数;末尾返回 -1 | 推荐!批量读取 |
| int read(char[] cbuf, int off, int len) | 读 len个字符到缓冲区,从 off 开始存储 | 精细控制读取范围 |
| void close() | 关闭流,释放资源 | 必须调用 |

5.2 文件实现类 : FileReader(文件字符输入流)

FileReader 是 Reader 的子类 , 用于文本文件读取字符(自动按系统默认编码)

构造方法 :

java 复制代码
// 1. 传入文件路径
Reader reader = new FileReader("D:/test.txt");
// 2. 传入 File 对象
File file = new File("D:/test.txt");
Reader reader = new FileReader(file);

示例 1 : 将文件完全读的两种方式

java 复制代码
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class demo10 {
    public static void main(String[] args) throws IOException {
        try(Reader reader = new FileReader("./test.txt")){
            while(true){
                char[] data = new char[1024];//缓冲区,也可以创建在循环外面重复使用
                int len = reader.read(data);//输出型参数
                //返回实际读取的字符个数,如果为-1表示已经读取完毕
                if(len == -1){
                    break;
                }
                for (int i = 0; i < len; i++) {
                    System.out.print(data[i]+" ");
                }
            }
        }
    }
    public static void main1(String[] args) throws IOException {
        try(Reader reader = new FileReader("./test.txt")){//这里要处理两个异常其中一个是IOException子类,另一个是IOException
            while(true){
                int data = reader.read();
                if(data == -1){
                    break;
                }
                System.out.printf("0x%x ",data);
            }
        }
    }
}

5.3 抽象基类 : Writer(字符输出流)

所有字符输出流的父类 , 是抽象类

核心方法 :

|---------------------------------------------|----------------------------|--------------|
| 方法签名 | 作用 | 备注 |
| void write(int c) | 写 1 个字符(c是 Unicode 码) | 单字符写入,效率低 |
| void write(char[] cbuf) | 把字符缓冲区的所有字符写入 | 批量写入,效率高 |
| void write(char[] cbuf, int off, int len) | 写入缓冲区从 off开始的 len个字符 | 精细控制写入范围 |
| void write(String str) | 直接写字符串(无需手动转字符数组) | 最常用!文本文件写入首选 |
| void write(String str, int off, int len) | 写字符串从 off开始的 len个字符 | 截取字符串写入 |
| void flush() | 刷新缓冲区(字符流必须调用,否则数据可能未写入磁盘) | 关键!避免数据丢失 |
| void close() | 关闭流(关闭前会自动刷新) | 必须调用 |

5.4 文件实现类 : FileWriter(文件字符输出流)

FileWriter 是 Writer 的子类 , 用于向文本文件写入字符

构造方法 :

java 复制代码
// 1. 覆盖写入
Writer writer = new FileWriter("D:/test.txt");
// 2. 追加写入
Writer writer = new FileWriter("D:/test.txt", true);
// 3. 传入 File 对象
File file = new File("D:/test.txt");
Writer writer = new FileWriter(file, true);

示例 1 : 写入字符

java 复制代码
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class demo11 {
    public static void main(String[] args) throws IOException {
        try(Writer writer = new FileWriter("./test.txt",true)){
            char[] data = {'*','[',']','{'};
            writer.write(data);

        }
    }
}

6.字节流 vs 字符流:关键差异

|-------|---------------------------------|--------------------------------|
| 对比维度 | 字节流(InputStream/OutputStream) | 字符流(Reader/Writer) |
| 操作单位 | 字节(byte) | 字符(char) |
| 编码依赖 | 无(直接操作原始字节) | 有(自动编码 / 解码,需统一编码) |
| 适用文件 | 所有文件(尤其是二进制文件:图片、视频、压缩包、.class) | 仅文本文件(.txt/.java/.md/.csv 等) |
| 核心方法 | read(byte[])/write(byte[]) | read(char[])/write(String) |
| 缓冲区刷新 | 可选(flush()可省略) | 必须(flush()否则数据可能滞留缓冲区) |

相关推荐
Dylan的码园33 分钟前
ArrayList与顺序表
java·数据结构·链表
Aevget33 分钟前
「Java EE开发指南」如何在MyEclipse中开发EJB 2 Session Bean?(二)
java·ide·java-ee·开发工具·myeclipse
带刺的坐椅33 分钟前
Solon AI 开发学习11 - chat - 工具调用与定制(Tool Call)
java·ai·llm·solon
sheji341637 分钟前
【开题答辩全过程】以 基于JavaWeb的高校实验实训教学平台为例,包含答辩的问题和答案
java·spring boot
艾莉丝努力练剑3 小时前
【C++:异常】C++ 异常处理完全指南:从理论到实践,深入理解栈展开与最佳实践
java·开发语言·c++·安全·c++11
武子康3 小时前
Java-184 缓存实战:本地缓存 vs 分布式缓存(含 Guava/Redis 7.2)
java·redis·分布式·缓存·微服务·guava·本地缓存
小马爱打代码9 小时前
Spring Boot:模块化实战 - 保持清晰架构
java·spring boot·架构
小坏讲微服务9 小时前
SpringBoot4.0整合knife4j 在线文档完整使用
java·spring cloud·在线文档·knife4j·文档·接口文档·swagger-ui
8***Z899 小时前
springboot 异步操作
java·spring boot·mybatis