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

如何在Play应用中访问txt文件?StopWordRemover类遇文件找不到异常

问题根源分析

这个问题我之前帮人排查过好几次,核心原因是Play应用运行时的工作目录和你独立运行类时完全不一样,而且Play对资源文件的加载逻辑有特殊处理:

  • 当你把StopWordRemover作为独立类运行时,JVM的工作目录就是你的项目根目录,所以./stopwords.txt这种相对路径能直接定位到文件。
  • 但Play应用不管是用sbt run启动,还是打包成jar/war运行,JVM的工作目录都不是你的项目根目录——比如sbt run时工作目录是sbt的临时运行目录,打包后jar里的资源也不是磁盘上的独立文件,这就导致相对路径完全失效。

另外你尝试的两个方案也有误区:

  • 把文件放到public文件夹:这个目录是给前端静态资源(比如JS、CSS、图片)准备的,通过controllers.routes.Assets.at()是给浏览器请求用的,后端Java/Scala代码不能直接用这个路径作为文件系统路径访问,打包后这些资源会被嵌入jar,根本不是磁盘文件。
  • 放到conf文件夹但还是用File类读取:conf里的文件会被打包到应用的classpath中,但File类只能访问磁盘上的物理文件,没法读取jar包内的资源,所以还是会报找不到文件。
正确解决方案

推荐用类加载器读取classpath资源的方式,这是Java/Scala应用读取内嵌资源的标准做法,不管是独立运行还是在Play框架里都能生效:

步骤1:放置文件

把stopwords.txt放到项目的conf目录下(这个目录的文件默认会被Play打包到classpath中)。

步骤2:修改读取代码

如果是Java实现的StopWordRemover:

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;

public class StopWordRemover {
    private Set<String> stopWords;

    public StopWordRemover() {
        stopWords = new HashSet<>();
        // 用类加载器获取资源流
        InputStream inputStream = getClass().getResourceAsStream("/stopwords.txt");
        if (inputStream == null) {
            throw new RuntimeException("Could not find stopwords.txt in classpath");
        }
        // 读取资源流内容
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            String line;
            while ((line = reader.readLine()) != null) {
                stopWords.add(line.trim());
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to load stopwords.txt", e);
        }
    }

    // 你的其他方法...
}

如果是Scala实现的StopWordRemover:

import scala.io.Source

class StopWordRemover {
  private val stopWords: Set[String] = {
    // 用类加载器获取资源
    val resource = getClass.getResourceAsStream("/stopwords.txt")
    if (resource == null) {
      throw new RuntimeException("Could not find stopwords.txt in classpath")
    }
    try {
      Source.fromInputStream(resource).getLines().map(_.trim).toSet
    } catch {
      case e: Exception => throw new RuntimeException("Failed to load stopwords.txt", e)
    } finally {
      resource.close()
    }
  }

  // 你的其他方法...
}

备选方案(仅当需要磁盘文件路径时)

如果你因为某些原因必须用File类访问(比如第三方库要求传入文件路径),可以通过Play的Environment组件获取应用的根目录,从而定位到conf下的文件:

Java版本(依赖注入):

import play.Environment;
import javax.inject.Inject;
import java.io.File;

public class StopWordRemover {
    private Set<String> stopWords;

    @Inject
    public StopWordRemover(Environment env) {
        stopWords = new HashSet<>();
        // 获取conf目录下的文件
        File stopWordsFile = env.getFile("conf/stopwords.txt");
        if (!stopWordsFile.exists()) {
            throw new RuntimeException("stopwords.txt not found in conf directory");
        }
        // 读取文件内容...
    }
}

注意:这个方案在Play打包成可执行jar时可能失效,因为jar里的conf文件不是磁盘上的独立文件,所以优先推荐类加载器的方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:38:06