首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【JavaSE】文件 IO 的常用核心类 && File 类 && try-with-resources && 字节流 && 字符流

【JavaSE】文件 IO 的常用核心类 && File 类 && try-with-resources && 字节流 && 字符流

原创
作者头像
lirendada
发布2026-04-18 10:26:50
发布2026-04-18 10:26:50
400
举报
文章被收录于专栏:JavaJava

Java IO 分为两个主要家族:

  1. 传统 IOjava.io 包):基于流(Stream,数据一个字节(字符)一个字节(字符)地流动。适合较小数据量、阻塞式处理。
  2. NIONew IOjava.nio 包):基于缓冲区(Buffer通道(Channel,更高效、支持非阻塞 IO(可用于高性能服务器),适合大规模并发处理。

这里主要介绍传统 IO,对于文件操作来说也主要用到的是传统 IO,而网络通信会用到 NIO,并且现在主流的框架已经集成了 NIO,所以不需要我们去调用 NIO 的原生 API,所以这里不重点展开学,等到后面学框架的时候再学习时候使用即可!

Ⅰ. 文件 IO 的常用核心类(来自 java.io 包)

类名

类型

功能

File

表示文件或目录,不进行读写

——

FileInputStream / FileOutputStream

字节流

用于读写文件(低级)

BufferedInputStream / BufferedOutputStream

字节缓冲流

加快读写速度,包装在流外层

FileReader / FileWriter

字符流

用于读写文本文件,单字符读取(低效)

BufferedReader / BufferedWriter

字符缓冲流

高效读写文本文件,提供按行读取等功能

InputStreamReader / OutputStreamWriter

转换流

字节流与字符流之间的桥梁

ObjectInputStream / ObjectOutputStream

对象流

支持对象的序列化与反序列化

💥注意事项:

  1. 其实因为 FileReaderFileWriter 的局限性,比如不能指定编码、功能较弱、封装层少等,所以一般处理字符流的时候,用的是 FileInputStreamFileOutputStream 分别搭配上 ScannerPrintWriter 即可!
  2. Java IO 使用装饰者模式Decorator),允许你用更强功能 "包裹" 基础流,如下所示:
代码语言:javascript
复制
// 字节流包裹
BufferedInputStream in = new BufferedInputStream(new FileInputStream("file.txt")); 

// 字符流包裹    
BufferedReader br = new BufferedReader(new FileReader("test.txt"))                 

Ⅱ. File

Filejava.io 包中的一个核心类,用于表示文件或目录的抽象路径名,但它本身不进行文件内容读写,而是用于检查、创建、删除、重命名文件和目录等 "元数据" 操作。

方法 / 构造器

返回类型

说明

File(String pathname)

构造器

通过路径字符串构造文件或目录

File(String parent, String child)

构造器

使用父路径 + 子路径构造

File(File parent, String child)

构造器

使用父 File + 子路径构造

exists()

boolean

路径是否存在

isFile()

boolean

是否是普通文件

isDirectory()

boolean

是否是目录

createNewFile()

boolean

创建文件(已存在时不创建)

mkdir()

boolean

创建目录(单层)

mkdirs()

boolean

创建目录(多层)

delete()

boolean

删除文件或空目录

getName()

String

获取文件/目录名

getPath()

String

返回构造 File 对象时传入的路径(原样返回,可能是相对路径)

getAbsolutePath()

String

获取绝对路径,但不解析符号链接或目录符号

getCanonicalPath()

String

获取绝对路径,解析符号链接、. 和 .. 等,等价于真实路径

getParent()

String

获取父路径(字符串)

length()

long

获取文件大小(字节)

lastModified()

long

最后修改时间戳(毫秒)

renameTo(File dest)

boolean

重命名或移动文件

list()

String[]

返回目录下的文件名数组

listFiles()

File[]

返回目录下的 File 对象数组

canRead() / canWrite()

boolean

是否可读 / 可写

setReadOnly()

boolean

设置为只读

isHidden()

boolean

是否是隐藏文件

举个例子,假如当前路径是 /home/user,然后代码如下所示:

代码语言:javascript
复制
File file = new File("../test.txt");
System.out.println("getPath(): " + file.getPath());
System.out.println("getAbsolutePath(): " + file.getAbsolutePath());
System.out.println("getCanonicalPath(): " + file.getCanonicalPath());

// 结果:
getPath(): ../test.txt
getAbsolutePath(): /home/user/../test.txt
getCanonicalPath(): /home/test.txt

题外话:try-with-resources⭐

try-with-resourcesJava 7 引入的一种简洁语法结构,用于自动关闭实现了 AutoCloseableCloseable 接口的资源,主要是确保资源在使用完毕后被自动关闭,即使中间发生异常,也不会泄露资源

传统写法有点累赘,不优雅,如下所示:

代码语言:javascript
复制
try {
    BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
    String line = reader.readLine();
    System.out.println(line);
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (reader != null) {
        try {
            reader.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

try-with-resources 写法如下所示:

代码语言:javascript
复制
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
    System.out.println(line);
} catch (IOException e) {
    e.printStackTrace();
}

优势:

  1. 更简洁
  2. 自动关闭资源(省去了 finally 块)
    1. try 中声明的资源,编译器会自动生成 finally 代码块来调用它们的 .close() 方法。
  3. 避免资源泄漏
    1. 即使 try 里面发生异常,Java 保证所有资源都被依次、倒序地关闭
    2. 如果 close() 方法本身也抛出异常,这些异常会被添加为抑制异常(suppressed exceptions,而不会吞掉原来的主异常。
  4. try 中可以有多个语句,需要; 分割即可!

Ⅲ. 字节流

字节流主要用于处理二进制数据(如图片、音频、视频、文件),分别有输入字节流和输出字节流,但它们都是抽象类,需要通过特定功能的子类来创建实例,我们重点放在文件相关的字节流类上!

抽象类

子类示例

InputStream

FileInputStream、BufferedInputStream、DataInputStream等等

OutputStream

FileOutputStream、BufferedOutputStream、DataOutputStream等等

下面是两者各自的方法以及共同的方法:

方法签名

返回类型

功能说明

🔹 FileInputStream 专属方法

int read()

int

读取单个字节(返回 0–255,返回 -1 表示 EOF)

int read(byte[] b)

int

读取多个字节,存入数组,返回实际读取的字节数

int read(byte[] b, int off, int len)

int

从偏移量 off 开始读取 len 个字节

int available()

int

返回可读取的字节数(非阻塞)

long skip(long n)

long

跳过 n 个字节,返回实际跳过的字节数

🔸 FileOutputStream 专属方法

void write(int b)

void

写出一个字节(仅低 8 位有效)

void write(byte[] b)

void

写出整个字节数组

void write(byte[] b, int off, int len)

void

从偏移量 off 写出 len 个字节

void flush()

void

强制刷新缓冲区,将数据立即写入文件

🔁 两者共有方法

void close()

void

关闭流并释放系统资源

FileDescriptor getFD()

FileDescriptor

获取底层文件描述符,用于底层文件操作(少用)

一、输入样例

代码语言:javascript
复制
public static void main(String[] args) {
    // try-with-resources风格:
    try(InputStream in = new FileInputStream("./main.txt")) {
        byte[] buf = new byte[1024];
        while(true) {
            int n = in.read(buf); // 磁盘数据读取到buf中
            if(n == -1) {
                System.out.println("读取完毕");
                break;
            }
            
            // 处理数据,比如输出数据
            for(int i = 0; i < n; ++i) {
                System.out.printf("0x%x\n", buf[i]); // 十六进制输出
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

二、输出样例

代码语言:javascript
复制
public static void main(String[] args) {
    try(OutputStream out = new FileOutputStream("./main1.txt")) {
        byte[] buf = {
            97, 98, 99, 100
        };
        out.write(buf); // 将buf数据写入到文件中去
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Ⅳ. 字符流

这里主要采用的还是文件字节流加上 ScannerPrintWriter 来处理字符,这两者分别有以下优势:

  1. Scanner 可以轻松地读取 int, double, String, 一行一行地处理文本(nextLine()nextInt() 等),还可以设置编码格式!又因为它接受 InputStream 作为输入源,所以能直接配合 FileInputStream 使用!
  2. PrintWriter 支持 print(), println(), printf() 等方法,并且支持 write(String),即可以传入 String 参数,这种支持是非常爽的!

一、输入样例

代码语言:javascript
复制
public static void main(String[] args) {
    try(InputStream in = new FileInputStream("./main.txt");
        Scanner sc = new Scanner(in, "UTF-8")) {
        
        // 循环读入每一行,然后输出
        while(sc.hasNext()) {
            String line = sc.nextLine();
            System.out.println(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

二、输出样例

代码语言:javascript
复制
public static void main(String[] args) {
    try(OutputStream out = new FileOutputStream("./main2.txt", "UTF-8");
        PrintWriter pw = new PrintWriter(out)) {

        // 将文本输出到文件中,可以直接传String类型
        pw.write("啊啊~利刃啊liren\n利刃阿斯顿");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Ⅰ. 文件 IO 的常用核心类(来自 java.io 包)
  • Ⅱ. File 类
  • 题外话:try-with-resources⭐
  • Ⅲ. 字节流
    • 一、输入样例
    • 二、输出样例
  • Ⅳ. 字符流
    • 一、输入样例
    • 二、输出样例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档