fileinputstream抛出filenotfoundexception说明路径错误、文件不存在或无访问权限,需用file.exists()和canread()主动验证;read()返回-1表示读完,循环中必须赋值判断;务必关闭流防句柄泄漏,大文件应选流式读而非readallbytes()。

FileInputStream 读取文件时抛出 FileNotFoundException 怎么办
这个异常不是“出错了”,而是明确告诉你:路径不对、文件不存在、或没权限访问。Java 不会帮你猜路径,FileInputStream 构造时就检查,不满足直接炸。
- 先用
new File(path).exists()和.canRead()主动验证,别等构造函数报错才排查 - 相对路径默认从 JVM 启动目录(不是项目根目录,更不是
src)开始找,建议统一用绝对路径或通过Class.getResourceAsStream()加载类路径资源 - Windows 下注意反斜杠:
"C:\data\test.bin"或用正斜杠"C:/data/test.bin",避免被当成转义字符
read() 返回 -1 就代表读完了?但为什么有时多读一次才停
read() 每次只读一个字节,返回 int(0–255),读到流末尾才返回 -1。问题常出在循环逻辑里——有人写成 while ((b = in.read()) != -1) { ... } 是对的,但若误写成 while (in.read() != -1),就会漏掉第一个字节,还可能多触发一次 read() 导致阻塞或异常。
- 必须把
read()的返回值赋给变量再判断,不能直接在条件中调用两次 - 批量读取更常用
read(byte[] b),它返回实际读到的字节数(可能小于数组长度),也以-1表示结束,但要注意:它不会自动清空数组剩余位置,旧数据可能残留 - 别依赖
available()判断是否读完——它只反映“当前可非阻塞读取的估计字节数”,对文件不一定准,对网络流基本不可靠
不关 FileInputStream 会怎样?try-with-resources 真的够用吗
不关流,文件句柄一直占着,Linux 下最多打开 1024 个文件是常见限制,跑久了直接 IOException: Too many open files;Windows 虽宽松些,但资源泄漏本质没变。
- 必须关闭——且要在
finally块里关,或用 try-with-resources(JDK 7+) - try-with-resources 确实够用,但前提是你的
FileInputStream是 final 或 effectively final 变量,否则编译不通过 - 如果流是方法参数传入的,别在方法里擅自关——调用方可能还要用,关了反而引发
IOException: Stream closed
和 Files.readAllBytes() 比,FileInputStream 适合什么场景
Files.readAllBytes() 简单粗暴,适合小文件(几 MB 内)。一旦文件上百 MB,直接 OOM;而 FileInputStream 是流式读,内存占用可控,适合大文件处理、边读边解析、或需要中断/跳过部分数据的情况。
立即学习“Java免费学习笔记(深入)”;
- 要随机访问(比如跳过前 100 字节再读),用
skip(long n),但注意它不保证跳够——返回值才是实际跳过的字节数,得检查 - 配合
BufferedInputStream能显著减少系统调用次数,尤其小块读时,别裸用FileInputStream - 如果目标是文本内容,别用
FileInputStream直接读字符串——它不处理编码,要用InputStreamReader包一层,否则中文大概率乱码
流操作真正麻烦的从来不是“怎么开”或“怎么读”,而是路径语义、生命周期归属、和边界条件的组合判断——比如你在一个容器里反复 new FileInputStream 却忘了 close,又或者在 finally 里重复 close 已经为 null 的流,这些细节比语法本身更容易让程序在半夜报警。










