为什么我可以从getClass().getResource()得到一个有效的url,但是返回的url创建了一个不存在的文件

Why can I get a valid url from getClass().getResource(), but the url that is returned creates a file that doesn't exist

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

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

与此同时,第二个 print 语句给出了“测试路径:/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 找到一个文件,那么我会假设该文件存在...

你的File test = new File(cFile),你的cFile是否正确制作,路径是否正确?也许最后的 print 语句只是在您创建的错误路径上拾取?但实际上你实际上没有文件。你手动检查过吗?

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


I am trying to load some data into an AWS lambda and am using getClass().getResource() to do so. This returns a nice URL that in logs seemingly prints out a plausible url;

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

However, when I try and make a file based on that path, I get a file that when I call .exists() returns false.

好的,除非 URL 有协议 "file:",否则我不希望它起作用。

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

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

  • 对于"http:"URL,协议处理程序建立到服务器的连接,发送一个GET请求,然后returns你一个流来读取响应正文。

  • 对于 "jar:" URL,协议处理程序打开 JAR 文件,在 JAR 文件中找到条目,并提供一个流供您读取。

  • 以此类推

如果您查看这些,只有在 "file:" 情况下,才有合理的预期将 URL 的路径组件视为文件系统路径名才可行。


查看问题中的路径名:

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

我推测原来的 URL 是:

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. 标识的资源
  3. 将其作为 JAR 文件流打开
  4. 在 JAR 文件的命名空间中找到条目“/com/my/package/folders/file.end”
  5. 打开流以读取该条目的内容。

JAR 文件协议处理程序知道如何执行此操作。但是(很明显)File class 没有...因为 "path" 不是文件系统路径名。


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

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

如果你这样做是因为你想给 "file" 写信,我建议你放弃这个想法。应用程序尝试更新其资源不是一个好主意。在某些情况下,它根本不会/无法工作。