15、Java 基础硬核复习:File类与IO流的核心逻辑与面试考点

15、Java 基础硬核复习:File类与IO流的核心逻辑与面试考点

在Java开发中,File类与IO流是连接程序与外部世界(文件、网络)的核心工具。即使现在有Spring等框架封装了IO操作,底层的流(Stream)概念和序列化机制依然是面试中的必考基础。本章逻辑清晰:先操作"文件本身"(File类),再操作"文件内容"(IO流)。

一、核心知识体系

1. File类:操作文件的"元数据"

java.io.File是文件或目录路径的抽象表示,只能操作文件的元数据 (如创建、删除、重命名、获取大小),不能修改文件内容

  • 路径问题
    • 绝对路径:从盘符(Windows)或根目录(Linux)开始的完整路径(如D:/a.txt);
    • 相对路径:相对于当前项目目录的路径(如src/a.txt),跨平台需用File.separator(如/\)。
  • 常用方法
    • 判断:exists()(是否存在)、isFile()(是否为文件)、isDirectory()(是否为目录);
    • 创建:createNewFile()(创建文件)、mkdir()(创建单级目录)、mkdirs()(创建多级目录);
    • 删除:delete()(删除文件/空目录,非空目录需先删文件);
    • 遍历:listFiles()(返回File对象数组,可结合递归遍历所有子目录和文件)。

2. IO流的分类与体系(重点)

IO流是数据传输的通道,分类依据如下:

  • 按数据单位
    • 字节流(Byte Stream):InputStream/OutputStream,操作8-bit,适合所有文件(图片、视频、音频);
    • 字符流(Character Stream):Reader/Writer,操作16-bit,只适合纯文本文件(如.txt、.java)。
  • 按流的角色
    • 节点流:直接作用于数据源(如FileInputStream读取文件);
    • 处理流:包在节点流外面,增强功能(如BufferedInputStream提供缓冲,ObjectInputStream实现序列化)。
  • 四大核心抽象基类
    所有流都继承自InputStream(字节输入流)、OutputStream(字节输出流)、Reader(字符输入流)、Writer(字符输出流)。

3. 重要流的实战

(1)文件流:操作文件内容
  • 字节流:FileInputStream(读二进制文件)、FileOutputStream(写二进制文件);
  • 字符流:FileReader(读文本文件)、FileWriter(写文本文件)。
(2)缓冲流:提升IO效率的"加速器"

缓冲流内部维护一个缓冲区(默认8KB),减少磁盘IO次数(批量读写),显著提升大文件处理速度。

  • 字节缓冲流:BufferedInputStream(读)、BufferedOutputStream(写);
  • 字符缓冲流:BufferedReader(读,提供readLine()方法)、BufferedWriter(写,提供newLine()方法)。
(3)转换流:解决"乱码"的关键

转换流是字节流与字符流的桥梁,核心功能是处理编码与解码(解决乱码问题)。

  • InputStreamReader:字节输入流 → 字符输入流(需指定编码,如new InputStreamReader(new FileInputStream("a.txt"), "GBK"));
  • OutputStreamWriter:字符输出流 → 字节输出流(同理,指定编码)。
(4)对象流:实现序列化与反序列化

对象流用于将Java对象转换为二进制流(持久化存储或网络传输)。

  • 序列化:ObjectOutputStream(将对象写入文件);
  • 反序列化:ObjectInputStream(将文件中的二进制流还原为对象);
  • 注意:类需实现Serializable接口(标记接口,无方法),serialVersionUID用于版本控制(反序列化时校验)。

二、高频面试考点(必须掌握)

1. 字节流 vs 字符流(🌟必考Top 1)

  • 区别
    • 字节流按8-bit传输,不处理编码;字符流按16-bit传输,内部根据编码表将字节转换为字符。
  • 选择
    • 纯文本文件(.txt、.java)→ 字符流;
    • 二进制文件(图片、视频、音频)→ 字节流(图片不能用字符流,二进制数据无法在编码表中找到对应字符,会导致数据损坏)。

2. read() vs read(byte[]/char[] buffer)(性能差异)

  • read():每次只读1个字节/字符,频繁操作磁盘,效率极低(类似"用勺子舀水");
  • read(buffer):每次读取一个数组的数据(如1024个),批量读写,效率高(类似"用铲子铲水")。

3. 序列化机制(Serialization)

  • 定义:将内存中的Java对象转换为二进制流(持久化存储或网络传输);
  • Serializable接口:标记接口,告诉JVM该类允许被序列化;
  • serialVersionUID :版本控制,序列化后修改类代码(未改ID)会导致反序列化失败(抛InvalidClassException)。

4. transient关键字(不想序列化的属性)

  • 作用:修饰属性(如密码、银行卡号),序列化时忽略该属性,反序列化时该值为默认值(null或0)。

5. 乱码问题(Encoding)

  • 原因:编码与解码使用的字符集不一致(如文件用UTF-8存,用GBK读);
  • 解决 :使用转换流(InputStreamReader),并在构造器中显式指定正确编码(如new InputStreamReader(new FileInputStream("a.txt"), "GBK"))。

6. close()flush()(资源释放)

  • close():自动调用flush()刷新缓冲区(将缓冲区数据写入文件),并释放系统资源(如文件句柄);
  • 不关闭的后果:文件被占用无法删除,或缓冲区数据丢失。
  • 现代Java开发推荐try-with-resources自动关闭流(如try (FileInputStream fis = new FileInputStream("a.txt")) {})。

三、学习建议

  1. 实操对比 :写一个"文件复制"工具,分别用字节流(FileInputStream+FileOutputStream)和缓冲流(BufferedInputStream+BufferedOutputStream)复制100MB视频,对比耗时(缓冲流效率更高);
  2. 乱码修复 :故意用错误编码读取文本文件(如GBK文件用UTF-8读),观察乱码,再用转换流修复(指定正确编码),这是解决生产环境Bug的基本功。
    掌握本章核心知识,不仅能应对面试,更能理解Java与外部交互的本质,为后续学习NIO、网络编程打下基础。
相关推荐
李少兄2 小时前
解决 org.springframework.context.annotation.ConflictingBeanDefinitionException 报错
java·spring boot·mybatis
大飞哥~BigFei2 小时前
整数ID与短字符串互转思路及开源实现分享
java·开源
空空潍2 小时前
Python核心基础语法
开发语言·python
benjiangliu2 小时前
LINUX系统-09-程序地址空间
android·java·linux
霍理迪2 小时前
JS其他常用内置对象
开发语言·前端·javascript
历程里程碑2 小时前
子串-----和为 K 的子数组
java·数据结构·c++·python·算法·leetcode·tornado
独自破碎E2 小时前
字符串相乘
android·java·jvm
jiayong232 小时前
Vue2 与 Vue3 常见面试题精选 - 综合宝典
前端·vue.js·面试
王多鱼鱼鱼2 小时前
QT如何将exe打包成可执行文件
开发语言·qt