运行Jar包时抛出NoSuchFileException,IDE内运行相同代码无异常
异常产生原因
- 代码中使用硬编码的Windows格式相对路径
..\\termproject\\word_database.txt定位词库文件,这类相对路径的解析基准是程序启动时的工作目录,和代码文件位置、Jar包存放位置没有绑定关系。 - IDE中运行项目时,IDE默认将项目根目录设为程序工作目录,此时该相对路径刚好能匹配到词库的存放位置,因此可以正常读取。
- 打包为Jar后,若你直接双击Jar运行,或是在命令行中切换到Jar所在目录执行启动命令,程序工作目录会变成Jar包所在的文件夹,原有相对路径无法匹配到词库位置,就会抛出
NoSuchFileException。 - 额外注意:硬编码
\\作为路径分隔符是Windows专属写法,在Linux/macOS系统下运行也会出现路径解析失败的问题;如果你打算把词库打包进Jar内部,用文件系统路径的写法也无法读取——Jar是压缩包格式,内部的资源不是文件系统上的独立文件,不能通过Paths.get()直接访问。
解决方案
根据你对词库文件的使用需求,二选一即可:
方案1:词库存放在Jar外部,支持后续手动修改
- 不要依赖可变的工作目录解析相对路径,直接以Jar包自身的存放位置为基准拼接文件路径,推荐把词库和Jar放在同一目录方便管理,代码示例:
import java.io.File; import java.net.URISyntaxException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.nio.file.Files; public String getwordleString() throws URISyntaxException { // 获取当前Jar包所在的绝对目录 File jarPath = new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()); String jarDir = jarPath.isDirectory() ? jarPath.getPath() : jarPath.getParent(); // 拼接词库路径,直接把word_database.txt放在Jar同级目录即可 Path path = Paths.get(jarDir, "word_database.txt"); List<String> wordList = new ArrayList<>(); try { wordList = Files.readAllLines(path); } catch (IOException e) { e.printStackTrace(); } Random random = new Random(); int position = random.nextInt(wordList.size()); return wordList.get(position).trim().toUpperCase(); }
- 这种写法自动适配不同操作系统的路径分隔符,只要词库和Jar放在同一文件夹,不管你从什么路径启动Jar都能正常读取。
方案2:词库为固定静态资源,打包进Jar内部
- 把
word_database.txt放到项目的resources资源目录下(Maven/Gradle项目标准资源目录,打包时会自动把目录下的文件打入Jar包),改用类加载器读取资源流,不要用文件系统路径访问:
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Random; public String getwordleString() { List<String> wordList = new ArrayList<>(); // 读取Jar包内的资源流 try (InputStream is = getClass().getClassLoader().getResourceAsStream("word_database.txt"); BufferedReader reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull(is), StandardCharsets.UTF_8))) { wordList = reader.lines().toList(); } catch (Exception e) { e.printStackTrace(); } Random random = new Random(); int position = random.nextInt(wordList.size()); return wordList.get(position).trim().toUpperCase(); }
- 这种方式完全不依赖外部文件和工作目录,Jar包拷贝到任意位置都能正常运行。
内容的提问来源于stack exchange,提问作者azra akın
相关产品推荐
相关产品推荐

