首页 > 解决方案 > 为什么我可以从 getClass().getResource() 获取有效的 url,但是返回的 url 会创建一个不存在的文件

问题描述

我正在尝试将一些数据加载到 AWS lambda 中,并使用 getClass().getResource() 来执行此操作。这会返回一个不错的 URL,在日志中似乎打印出一个合理的 url;但是,当我尝试根据该路径创建文件时,我得到一个文件,当我调用 .exists() 时返回 false。

如果我运行下面的代码,第一个打印语句给出“returns exists: false”

同时,第二个打印语句围绕“测试路径:/file:/var/task/lib/MyLambda-1.0.jar!/com/my/package/folders/file.end

File test = new File(cFile);
System.out.println("exists: " + test.exists());
System.out.println("test path: " + test.getAbsolutePath());

不知道为什么会这样。如果Java找到一个文件,那么我会假设该文件存在......

标签: javaamazon-web-servicesfileaws-lambdagetresource

解决方案


简短的回答:不要假设 URL 的“路径”是文件系统路径名。


我正在尝试将一些数据加载到 AWS lambda 中,并使用 getClass().getResource() 来执行此操作。这会返回一个不错的 URL,在日志中似乎打印出一个合理的 url;

是的。(如果您向我们展示原始 URL 的样子,那就太好了……尽管我可以猜到。)

但是,当我尝试根据该路径创建文件时,我会得到一个文件,当我调用 .exists() 时会返回 false。

好的,除非 URL 具有协议“文件:”,否则我不希望它起作用。

URL 中的路径是供协议处理程序解析的路径。这个想法是您使用URL::openStream打开一个流到由 URL 命名的资源然后读取它。协议处理程序负责解释路径(等)并设置流。

  • 对于“file:” URL,协议处理程序将解析文件系统中的路径,并为您提供读取文件的流。

  • 对于“http:” URL,协议处理程序建立与服务器的连接,发送 GET 请求,并返回一个流以读取响应正文。

  • 对于“jar:”URL,协议处理程序会打开 JAR 文件,在 JAR 文件中找到条目,然后交给您一个流来读取它。

  • 等等。

如果您查看这些,只有在“文件:”的情况下,才有合理的期望将 URL 的路径组件视为文件系统路径名可以工作。


查看问题中的路径名:

file:/var/task/lib/MyLambda-1.0.jar!/com/my/package/folders/file.end

我猜原来的网址是:

jar:file:/var/task/lib/MyLambda-1.0.jar!/com/my/package/folders/file.end

所以这对“jar:”协议处理程序说的是:

  1. 查找由 URL “file:/var/task/lib/MyLambda-1.0.jar”标识的资源
  2. 将其作为 JAR 文件流打开
  3. 在 JAR 文件的命名空间中找到条目“/com/my/package/folders/file.end”
  4. 打开一个流以读取该条目的内容。

JAR 文件协议处理程序知道如何做到这一点。但是(显然)File该类没有......因为该“路径”不是文件系统路径名。


你如何解决这个问题取决于你真正需要什么。

  • 如果您只需要一个流来读取资源,请getClass().getResourceAsStream(...)改用。
  • 如果它必须是文件系统中的一个文件,您可能必须获取流(见上文),将其复制到一个临时文件,并使用 aFile作为临时文件。

如果您这样做是因为您想写入“文件”,我建议您放弃这个想法。应用程序尝试更新其资源是一个坏主意。在某些情况下,它根本不会/无法工作。


推荐阅读