如何从 .jar 文件中包含的 ZIP 文件加载图像?
How do you load an Image from a ZIP file contained in a .jar file?
我们正在编写一个游戏,应该可以从 .jar 文件启动。首先,我们在 IntelliJ 中创建了一个项目,并使用以下代码从 ZIP 文件中加载图像:
ZipFile zf = null;
try {
zf = new ZipFile(zipPath);
Image Image = ImageIO.read(zf.getInputStream(zf.getEntry("Block/Air.png")));
} catch (IOException ignored) {}
现在没有 ZIP 的尝试(仅来自 .jar)是:
Image image=ImageIO.read(getClass().getResourceAsStream(path+ "Block/Air.png"));
它不加载任何纹理。你有更好的组合方式吗?
编辑:似乎不是问题所在。
为什么需要将图像存储在 zip 文件中?如果您这样做是为了减小文件大小,那么先压缩它绝对没有任何好处。 JAR 文件无论如何都是压缩文件(如果您不相信我,请将您的 .jar 文件重命名为 .zip,然后尝试打开它)。你基本上在做的是尝试压缩一个已经压缩的文件,这实际上并没有做任何事情。
我建议您解压缩图像并将它们存储在 /images 之类的地方
如果您坚持让它们保持压缩状态,则需要将其更改为类似这样的内容。否则,它会在工作目录(执行 jar 的目录)中寻找 zip 文件
ZipFile zf = new ZipFile(getClass().getResourcesAsStream("path/to/zip"));
免责声明:我不熟悉 ZipFile class,所以我不知道该构造函数是否存在。
由于 jars 是 zip 文件,您可以将它们放在 jar 文件中并将它们放在类路径中。
Image image=ImageIO.read(getClass().getResourceAsStream(path+ "Block/Air.png");
路径必须是源路径根的相对路径。例如。我在 "src/main/resource/my/cool/game/" 路径中有一个文件是“/my/cool/game”。
如果您想使用 zip 文件,它必须在您的 jar 文件之外。要加载 zip,您可以使用相对文件路径,如果您从 Intellij 和 dekstop 启动游戏,该路径是相同的。
在intellij中更改工作目录look here。
最好的方法是将 zip 文件放在 jar 文件旁边,这样您就可以使用“.”了。作为加载 zip 文件的工作目录。
或者您可以使用固定目录,但您的游戏需要进行某种安装,以便它知道在哪里可以找到 zip 文件。
如果使用“.”,zip 文件需要位于项目目录的根目录中。
Class.getResource 和 Class.getResourceAsStream 方法采用 URL(不是文件路径!),它 相对于每个类路径条目的根目录。 对于 .jar 文件的类路径条目,这意味着打包在相应 .jar 文件中的文件的路径。
如果您的整个程序都在一个 .jar 文件中,则类路径仅包含一项:该 .jar 文件。因此,只有一个类路径根,传递给 getResourceAsStream 的字符串是 .jar 文件中条目的 URL。不要在该字符串中包含 .jar 文件的路径。
如果您不确定应该传递什么,请检查您的 .jar 文件的内容。每个 IDE(据我所知)都提供了执行此操作的方法。您还可以使用任何解压缩实用程序来检查 .jar 文件,因为每个 .jar 文件实际上都是一个 .zip 文件。 (如果您只有 Windows,没有安装 zip 工具,请复制 .jar 文件并将副本的扩展名更改为“.zip”,然后打开它。)
.jar 文件中当然包含 zip 条目。要加载的条目的完整路径(不包括 .jar 文件的路径)是您必须传递给 getResourceAsStream 的内容。 getResourceAsStream 接受 URL,并且 URL 在所有平台上始终使用正斜杠 (/
),因此不要使用任何反斜杠。此外,字符串的第一个字符必须是 /
.
实际上可以指定较短的路径,具体取决于图像在 .jar 中的打包方式,但这是一个单独的主题。有关详细信息,请参阅 the documentation。
旁注:永远不要写一个空的 catch 块。曾经。捕获的异常是迄今为止您或任何其他人了解您的程序何时以及为何无法运行的最简单方法。至少,将 exc.printStackTrace();
放在你的 catch 块中。更多时候,正确的做法是用 throw new RuntimeException(exc);
之类的东西中止程序。毕竟,如果无法加载该图像,您的程序将无法继续正常运行,对吗?
我们正在编写一个游戏,应该可以从 .jar 文件启动。首先,我们在 IntelliJ 中创建了一个项目,并使用以下代码从 ZIP 文件中加载图像:
ZipFile zf = null;
try {
zf = new ZipFile(zipPath);
Image Image = ImageIO.read(zf.getInputStream(zf.getEntry("Block/Air.png")));
} catch (IOException ignored) {}
现在没有 ZIP 的尝试(仅来自 .jar)是:
Image image=ImageIO.read(getClass().getResourceAsStream(path+ "Block/Air.png"));
它不加载任何纹理。你有更好的组合方式吗?
编辑:似乎不是问题所在。
为什么需要将图像存储在 zip 文件中?如果您这样做是为了减小文件大小,那么先压缩它绝对没有任何好处。 JAR 文件无论如何都是压缩文件(如果您不相信我,请将您的 .jar 文件重命名为 .zip,然后尝试打开它)。你基本上在做的是尝试压缩一个已经压缩的文件,这实际上并没有做任何事情。
我建议您解压缩图像并将它们存储在
如果您坚持让它们保持压缩状态,则需要将其更改为类似这样的内容。否则,它会在工作目录(执行 jar 的目录)中寻找 zip 文件
ZipFile zf = new ZipFile(getClass().getResourcesAsStream("path/to/zip"));
免责声明:我不熟悉 ZipFile class,所以我不知道该构造函数是否存在。
由于 jars 是 zip 文件,您可以将它们放在 jar 文件中并将它们放在类路径中。
Image image=ImageIO.read(getClass().getResourceAsStream(path+ "Block/Air.png");
路径必须是源路径根的相对路径。例如。我在 "src/main/resource/my/cool/game/" 路径中有一个文件是“/my/cool/game”。
如果您想使用 zip 文件,它必须在您的 jar 文件之外。要加载 zip,您可以使用相对文件路径,如果您从 Intellij 和 dekstop 启动游戏,该路径是相同的。
在intellij中更改工作目录look here。
最好的方法是将 zip 文件放在 jar 文件旁边,这样您就可以使用“.”了。作为加载 zip 文件的工作目录。
或者您可以使用固定目录,但您的游戏需要进行某种安装,以便它知道在哪里可以找到 zip 文件。
如果使用“.”,zip 文件需要位于项目目录的根目录中。
Class.getResource 和 Class.getResourceAsStream 方法采用 URL(不是文件路径!),它 相对于每个类路径条目的根目录。 对于 .jar 文件的类路径条目,这意味着打包在相应 .jar 文件中的文件的路径。
如果您的整个程序都在一个 .jar 文件中,则类路径仅包含一项:该 .jar 文件。因此,只有一个类路径根,传递给 getResourceAsStream 的字符串是 .jar 文件中条目的 URL。不要在该字符串中包含 .jar 文件的路径。
如果您不确定应该传递什么,请检查您的 .jar 文件的内容。每个 IDE(据我所知)都提供了执行此操作的方法。您还可以使用任何解压缩实用程序来检查 .jar 文件,因为每个 .jar 文件实际上都是一个 .zip 文件。 (如果您只有 Windows,没有安装 zip 工具,请复制 .jar 文件并将副本的扩展名更改为“.zip”,然后打开它。)
.jar 文件中当然包含 zip 条目。要加载的条目的完整路径(不包括 .jar 文件的路径)是您必须传递给 getResourceAsStream 的内容。 getResourceAsStream 接受 URL,并且 URL 在所有平台上始终使用正斜杠 (/
),因此不要使用任何反斜杠。此外,字符串的第一个字符必须是 /
.
实际上可以指定较短的路径,具体取决于图像在 .jar 中的打包方式,但这是一个单独的主题。有关详细信息,请参阅 the documentation。
旁注:永远不要写一个空的 catch 块。曾经。捕获的异常是迄今为止您或任何其他人了解您的程序何时以及为何无法运行的最简单方法。至少,将 exc.printStackTrace();
放在你的 catch 块中。更多时候,正确的做法是用 throw new RuntimeException(exc);
之类的东西中止程序。毕竟,如果无法加载该图像,您的程序将无法继续正常运行,对吗?