ClassLoader.getResource 返回奇怪的路径(也许)?

Cam*_*ell 5 java path classloader

从资源文件夹加载文本文件等资源时,最常见的方法是使用 ClassLoader 获取路径:

String path = getClass().getClassLoader().getResource("file.txt").getPath();
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用 java 具有的众多读取器中的任何一个来读取该文件的内容。但由于某种原因,Paths.get(path)对这条路不满意:

byte[] content = Files.readAllBytes(Paths.get(path)) 
    -> throws java.nio.file.InvalidPathException when executed
Run Code Online (Sandbox Code Playgroud)

ClassLoader.getResource(...).getPath() 正在返回:

/D:/Projects/myapp/build/resources/main/file.txt
Run Code Online (Sandbox Code Playgroud)

Paths.get()不喜欢它。显然后面的“:”/D是“非法字符”。(注意,路径看起来是正确的,文件实际上在那里)

哪一个导致了问题?是ClassLoader.getResource()返回无效路径还是Paths.get()无故行为?


一段时间后
,java中的路径似乎有多种不同的格式。各种框架似乎并不完全同意什么是正确的,什么是错误的,因此它们创建和接受的路径之间存在各种差异。

在此示例中,Paths.get()实际上并不期望路径中存在前导斜杠:

/D:/Projects/myapp/build/resources/main/vertex.vs.glsl <- EVIL
D:/Projects/myapp/build/resources/main/vertex.vs.glsl <- OK
Run Code Online (Sandbox Code Playgroud)

我想现在的问题是:如何清理返回的文件路径ClassLoader.getResource()以正确使用Paths.get()?这两种文件路径格式之间还有其他区别吗?

TmT*_*ron 6

  1. “最常见的方法”不一定是最好的:)
  2. 请注意您指的是哪个路径:ClassLoader.getResource()返回一个 URL,该 URL 可以包含路径组件。但是,这不一定是有效的文件路径。
    请注意,还有一个方法Paths.get(URI)它将URI作为参数
  3. 第一个斜杠/D:/Projects/myapp/build/resources/main/file.txt仅表示这是一个绝对路径:请参阅Class.getResource
  4. 我建议,当您想读取文件时,您只需使用ClassLoader.html#getResourceAsStream

更新回答评论:“那么为什么 Paths.get() 不接受绝对路径?”

Paths.get() 确实接受绝对路径。
但您必须传递有效的(文件)路径 - 在您的情况下,您直接传递 URL 路径(这不是有效的文件路径)。

  • 当你调用:getClass().getClassLoader().getResource("file.txt")它返回一个 URL:file:/D:/Projects/myapp/build/resources/main/file.txt
    • 该 URL 由架构组成file:
    • 以及有效(绝对 URL)路径:/D:/Projects/myapp/build/resources/main/file.txt
  • 您尝试直接使用此 URL 路径作为文件路径,这是错误的

要将 URL 路径转换为有效的文件路径,您可以使用Paths.get(URI)方法,如下所示:

URL fileUrl = getClass().getClassLoader().getResource("file.txt");
Path filePath = Paths.get(fileUrl.toURI());
// now you have a valid file-path: D:/Projects/myapp/build/resources/main/file.txt
Run Code Online (Sandbox Code Playgroud)

  • `Paths.get` 返回类型 `Path`,而不是 `String`? (2认同)