You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jar包中FileOutputStream无法找到txt文件,求技术解决方案

问题分析与解决方案

这个问题其实挺常见的——IDE里跑着一切正常,打包成Jar就找不到文件,核心原因主要有两个:

1. 路径逻辑完全错配

你用的"src/resources/highscore.txt"是IDE项目结构里的相对路径,但打包成Jar后,这个路径根本不存在:Jar文件不会保留src目录,你的资源文件会被放到Jar的根目录(类路径根路径)。更关键的是,Jar是压缩文件,你没法用FileOutputStream直接写入Jar内部的文件,哪怕路径写对了也不行,因为Jar内的资源是只读的。

2. getResource()的用法误区

this.getClass().getResources(path)是用来读取类路径下的只读资源的(比如配置文件、静态图片),但它不能用来定位可写入的文件——因为写入需要一个在文件系统中真实存在、且有写入权限的路径,而不是Jar包内部的资源路径。


正确解决方案:把数据文件放到外部可写目录

最佳实践是把用户数据(比如高分榜)存到操作系统的用户专属可写目录里,比如Windows的C:\Users\[你的用户名]\AppData\Roaming,或者Linux/macOS的~/.your-app-name。不管是IDE运行还是Jar运行,都能找到稳定的可写入位置。

改造后的代码示例

public void setPlayer() { 
    ArrayList<Player> playerArrayList = getPlayers(); 
    Player player = new Player(); 
    player.name = ViewManager.name; 
    player.score = Collision.points; 
    playerArrayList.add(player); 

    // 步骤1:获取外部可写目录(这里用用户home目录下的专属文件夹)
    File appDataDir = new File(System.getProperty("user.home"), ".my-game-highscores");
    if (!appDataDir.exists()) {
        appDataDir.mkdirs(); // 目录不存在就创建
    }
    File highScoreFile = new File(appDataDir, "highscore.txt");

    // 步骤2:写入数据到外部文件(用try-with-resources自动关流)
    try (FileOutputStream fileOut = new FileOutputStream(highScoreFile);
         ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
        for(Player player1 : playerArrayList){
            out.writeObject(player1);
        }
    } catch (IOException e) { 
        e.printStackTrace(); 
    } 
}

// 对应的读取方法也要同步改造
public ArrayList<Player> getPlayers() {
    ArrayList<Player> playerArrayList = new ArrayList<>();
    File appDataDir = new File(System.getProperty("user.home"), ".my-game-highscores");
    File highScoreFile = new File(appDataDir, "highscore.txt");
    
    if (!highScoreFile.exists()) {
        return playerArrayList; // 文件不存在时返回空列表
    }

    try (FileInputStream fileIn = new FileInputStream(highScoreFile);
         ObjectInputStream in = new ObjectInputStream(fileIn)) {
        while (true) {
            try {
                Player p = (Player) in.readObject();
                playerArrayList.add(p);
            } catch (EOFException e) {
                break; // 读到文件末尾就退出循环
            }
        }
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
    return playerArrayList;
}

额外提醒

  • 确保Player类已经实现了Serializable接口,否则序列化会失败(你IDE里能运行,应该已经实现了,但还是提一句)。
  • 用try-with-resources语法自动关闭流,比手动调用close()更安全,能避免资源泄漏。
  • 给你的应用专属目录起个辨识度高的名字,比如".space-war-highscores",避免和其他应用的文件冲突。

内容的提问来源于stack exchange,提问作者user10751443

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:12:34