使用FileInputStream加载文件报错:找不到文件或目录,求排查原因
为什么
new FileInputStream(f.getAbsoluteFile())正常,直接用f却报找不到文件? 这问题我之前也踩过坑,核心原因其实和**File对象的路径解析逻辑以及当前工作目录的变化**有关,我给你拆解清楚:
关键知识点:File对象的本质
File对象只是对文件路径的抽象封装,它不会在创建时就自动把相对路径转换成绝对路径——除非你主动调用getAbsoluteFile()或getAbsolutePath()方法。而且,相对路径的File对象,每次被使用时(比如传给FileInputStream),都会基于当时的当前工作目录(System.getProperty("user.dir"))来解析路径,而不是创建File对象时的工作目录。
你的问题场景分析
你遇到的情况,大概率是下面这个流程:
- 你在工作目录A下创建了
File f = new File("./build/classes/" + path),此时f保存的是相对路径字符串; - 在创建
f之后、调用new FileInputStream(f)之前,你的代码(或者你用的框架)把当前工作目录改成了B; - 当你直接用
f创建FileInputStream时,JVM会在工作目录B下去找./build/classes/xxx,而这个路径在B下不存在,所以抛出FileNotFoundException; - 但如果先调用
f.getAbsoluteFile(),这个方法会在**调用它的那一刻(也就是工作目录还是A的时候)**把相对路径解析成绝对路径,生成一个新的File对象。后续不管工作目录怎么变,用这个绝对路径的File创建FileInputStream,都会直接去正确的绝对路径找文件,自然不会报错。
验证方法
你可以在两段代码中加入打印,确认工作目录的变化:
File f = new File("./build/classes/" + path); // 打印当前工作目录和f的路径 System.out.println("当前工作目录: " + System.getProperty("user.dir")); System.out.println("f的相对路径: " + f.getPath());
对比两种写法的打印结果,你会发现:直接用f的那段代码,在创建FileInputStream时的工作目录,已经和创建f时的不一样了。
解决方案
- 如果你无法保证工作目录不会变化,创建
File对象后立即获取绝对路径,用绝对路径的File对象来操作文件; - 尽可能避免使用相对路径,改用项目根目录的绝对路径来构造文件路径(比如通过
ClassLoader.getResource()获取资源的绝对路径)。
内容的提问来源于stack exchange,提问作者saaav
相关产品推荐
相关产品推荐

