如何使用相对路径而不是绝对路径
How to use relative path instead of absolute
所以我需要为 Intellij IDEA 插件设置一个图标,但是当我试图使用 new File(relative path)
或 getClass().getResource(relative path)
从我的项目中获取这个图标时。它找不到文件,只能使用绝对路径。我试过以下相对路径:
images/icon.png
resources/images/icon.png
main/resources/images/icon.png
src/main/resources/images/icon.png
图标路径: src/main/resources/images/icon.png
源代码路径: src/main/java/com/timetrack/plugin/MyClass.java
代码:
File file = new File("src/main/resources/images/running.png");
BufferedImage img = ImageIO.read(file);
或用这个
BufferedImage img = ImageIO.read(getClass().getResource("images/running.png"));
编辑
需要说明的是,我正在使用 Gradle 来构建项目。所以输出目录如下所示:
图标路径:build/resources/main/images/icon.png
已编译类:
build/classes/java/main/com/timetrack/plugin/MyClass.class
您的资源字符串需要以斜杠开头,因为它与您的 class.
不在同一个包中
转述自the documentation of getResource:
- If the name begins with a
/
, then the absolute name of the resource is the portion of the name following the /
.
- Otherwise, the absolute name is of the form modified_package_name/name, where the modified_package_name is the package name of this class with
/
substituted for .
.
换句话说,传递给 Class.getResource 的参数被假定为与 Class 本身在同一个包中,除非参数以斜杠开头。
这是因为在应用程序或库中包含资源的正确方法是将它们放在与使用它们的 class 相同的包目录中。这样做的原因与我们使用包的原因相同。就此而言,这与应用程序不将其所有文件存储在用户的主目录或 C:\
中的原因相同:因为存在其他程序选择相同名称并干扰您的程序的真正风险。
Class.getResource 在 class 路径中搜索请求的资源。如果您将图标打包为 images/running.png
,并且图书馆也决定将其图像打包为 images/running.png
,那么 Class.getResource 将搜索 class 路径和 return 任何内容它首先找到。根据 classpath 条目的顺序,要么你会得到错误的图像,要么其他图书馆会。两者本质上是在互相踩踏。
另一方面,如果您将图像放在 src/main/resources/com/timetrack/plugin/running.png
,则任何其他代码都不太可能使用该包,因此发生冲突的可能性很小。因为这是最常见的用例,所以以这种方式使用它更容易:您可以仅使用 MyClass.class.getResource("running.png")
.
检索图像 URL
所以我需要为 Intellij IDEA 插件设置一个图标,但是当我试图使用 new File(relative path)
或 getClass().getResource(relative path)
从我的项目中获取这个图标时。它找不到文件,只能使用绝对路径。我试过以下相对路径:
images/icon.png
resources/images/icon.png
main/resources/images/icon.png
src/main/resources/images/icon.png
图标路径: src/main/resources/images/icon.png
源代码路径: src/main/java/com/timetrack/plugin/MyClass.java
代码:
File file = new File("src/main/resources/images/running.png");
BufferedImage img = ImageIO.read(file);
或用这个
BufferedImage img = ImageIO.read(getClass().getResource("images/running.png"));
编辑
需要说明的是,我正在使用 Gradle 来构建项目。所以输出目录如下所示:
图标路径:build/resources/main/images/icon.png
已编译类:
build/classes/java/main/com/timetrack/plugin/MyClass.class
您的资源字符串需要以斜杠开头,因为它与您的 class.
不在同一个包中转述自the documentation of getResource:
- If the name begins with a
/
, then the absolute name of the resource is the portion of the name following the/
.- Otherwise, the absolute name is of the form modified_package_name/name, where the modified_package_name is the package name of this class with
/
substituted for.
.
换句话说,传递给 Class.getResource 的参数被假定为与 Class 本身在同一个包中,除非参数以斜杠开头。
这是因为在应用程序或库中包含资源的正确方法是将它们放在与使用它们的 class 相同的包目录中。这样做的原因与我们使用包的原因相同。就此而言,这与应用程序不将其所有文件存储在用户的主目录或 C:\
中的原因相同:因为存在其他程序选择相同名称并干扰您的程序的真正风险。
Class.getResource 在 class 路径中搜索请求的资源。如果您将图标打包为 images/running.png
,并且图书馆也决定将其图像打包为 images/running.png
,那么 Class.getResource 将搜索 class 路径和 return 任何内容它首先找到。根据 classpath 条目的顺序,要么你会得到错误的图像,要么其他图书馆会。两者本质上是在互相踩踏。
另一方面,如果您将图像放在 src/main/resources/com/timetrack/plugin/running.png
,则任何其他代码都不太可能使用该包,因此发生冲突的可能性很小。因为这是最常见的用例,所以以这种方式使用它更容易:您可以仅使用 MyClass.class.getResource("running.png")
.