java - 外部 jar 中的资源加载不起作用

标签 java eclipse jar lwjgl slick2d

我正在使用 LWJGL 和 Slick2d 制作游戏,自然有游戏资源可以导出到我的 jar 中使用。但是,它们无法从我使用 jarsplice 创建的可运行 .jar 中加载,但当它们与 .jar 文件位于同一文件夹中时运行。我尝试使用 .getSystemResource() 和 .getSystemResourceAsStream() 在 Eclipse 中加载源代码中的文件来解决此问题,但它不起作用。我花了几个小时在 stackoverflow、gamedev.net、lwjgl 论坛和 slick2d 论坛中搜索以加载从 Eclipse 导出的 jar 中的资源,但无济于事。这是我经历的过程:

1)我配置我的构建路径 - 包含所有内容,不排除任何内容。

2) 所有库均已正确添加;

3) 所有内容均已选择用于订购和导出。

4) 我导出为通用(不可运行).jar,取消选择我的代码未引用的那些文件夹和包。包含我的音频、图像和着色器的那些文件夹已正确标记为导出。

/image/wj4Pt.jpg

5) 我打开 .jar 文件,所有内容都在里面。此时, list 文件为空。

6) 我使用 jarsplice 创建一个 fat .jar,首先添加 .jar 文件;

7) 接下来我添加 lwjgl 所需的所有 native ;

8)最后我使用完整的包路径进入我的主类。

9)当我创建 .jar 并查看内部时,所有内容都按其应有的样子包含在内。

/image/FMH7B.jpg

此外, list 文件现在已正确填写:

Manifest-Version: 1.0
Launcher-VM-Args: 
Launcher-Main-Class: com.fafnir.gestalt.Bootstrap
Main-Class: org.ninjacave.jarsplice.JarSpliceLauncher

10) 在使用“java -jar FatRunnable.jar”运行 .jar 时,我收到错误,因此我创建一个 .bat 文件来运行它并将输出记录在文本文件中:

java -jar FatRunnable.jar %* > log.txt
PAUSE

11)我检查文本文件并看到以下内容:

Wed Jul 30 17:42:11 EDT 2014 INFO:Initialising sounds..
[LWJGL] getPathFromClassLoader: searching for: OpenAL32
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException: sun.misc.Launcher$AppClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.net.URLClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.security.SecureClassLoader.findLibrary(java.lang.String)
[LWJGL] getPathFromClassLoader: searching for: lwjgl
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException: sun.misc.Launcher$AppClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.net.URLClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.security.SecureClassLoader.findLibrary(java.lang.String)
[LWJGL] getPathFromClassLoader: searching for: lwjgl
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException: sun.misc.Launcher$AppClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.net.URLClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.security.SecureClassLoader.findLibrary(java.lang.String)
[LWJGL] Found 6 OpenAL paths
[LWJGL] Testing 'C:\Users\MOTHAF~1\AppData\Local\Temp\\natives-1942957663\OpenAL64.dll'
[LWJGL] Found OpenAL at 'C:\Users\MOTHAF~1\AppData\Local\Temp\\natives-1942957663\OpenAL64.dll'
[LWJGL] MemoryUtil Accessor: AccessorUnsafe
Wed Jul 30 17:42:11 EDT 2014 INFO:- Sound works
Wed Jul 30 17:42:11 EDT 2014 INFO:- 64 OpenAL source available
Wed Jul 30 17:42:11 EDT 2014 INFO:- Sounds source generated
[LWJGL] Initial mode: 1600 x 900 x 32 @60Hz
[LWJGL] Found 32 displaymodes
[LWJGL] Removed 20 duplicate displaymodes
Detected display modes:
800x600x32 60Hz
1600x900x16 60Hz
640x480x16 60Hz
1024x768x16 60Hz
1280x720x32 60Hz
1280x800x16 60Hz
800x600x16 60Hz
1600x900x32 60Hz
640x480x32 60Hz
1024x768x32 60Hz
1280x720x16 60Hz
1280x800x32 60Hz
[LWJGL] GL_EXT_direct_state_access was reported as available but an entry point is missing
OpenGL version: 3.2.9712 Core Profile Forward-Compatible Context
Could not read file.
java.io.FileNotFoundException: glsl\textured.vs (The system cannot find the path specified)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:131)
    at java.io.FileInputStream.<init>(FileInputStream.java:87)
    at java.io.FileReader.<init>(FileReader.java:58)
    at com.fafnir.gestalt.quads.QuadUpdateVBO.loadShader(QuadUpdateVBO.java:180)
    at com.fafnir.gestalt.quads.QuadUpdateVBO.setupShaders(QuadUpdateVBO.java:146)
    at com.fafnir.gestalt.quads.QuadUpdateVBO.<init>(QuadUpdateVBO.java:49)
    at com.fafnir.gestalt.Bootstrap.setupArtists(Bootstrap.java:167)
    at com.fafnir.gestalt.Bootstrap.<init>(Bootstrap.java:72)
    at com.fafnir.gestalt.Bootstrap.main(Bootstrap.java:38)
AL lib: (EE) alc_cleanup: 1 device not closed
Could not locate symbol glEnableClientStateiEXT
Could not locate symbol glDisableClientStateiEXT
Could not locate symbol glGetFloati_vEXT
Could not locate symbol glGetDoublei_vEXT
Could not locate symbol glGetPointeri_vEXT
Could not locate symbol glNamedCopyBufferSubDataEXT
Could not locate symbol glVertexArrayIndexOffsetEXT
Could not locate symbol glVertexArrayVertexAttribOffsetEXT
Could not locate symbol glVertexArrayVertexAttribIOffsetEXT
Could not locate symbol glEnableVertexArrayEXT
Could not locate symbol glDisableVertexArrayEXT
Could not locate symbol glEnableVertexArrayAttribEXT
Could not locate symbol glDisableVertexArrayAttribEXT
Could not locate symbol glGetVertexArrayIntegervEXT
Could not locate symbol glGetVertexArrayPointervEXT
Could not locate symbol glGetVertexArrayIntegeri_vEXT
Could not locate symbol glGetVertexArrayPointeri_vEXT
Could not locate symbol glMapNamedBufferRangeEXT
Could not locate symbol glFlushMappedNamedBufferRangeEXT

12) 看起来,尽管着色器位于 .jar 文件中,但它无法找到位于“glsl”文件夹中的着色器。据我所知,这是因为它们不是单独的文件,而是位于 .jar 内,并且必须使用不同的代码进行访问。

通过将文件路径以及 GL20 值传递给我的 loadShader(String fileName, int type) 方法来加载着色器:

// Load the vertex shader
vsId = loadShader("glsl/textured.vs", GL20.GL_VERTEX_SHADER);

// Load the fragment shader
fsId = loadShader("glsl/textured.fs", GL20.GL_FRAGMENT_SHADER);

13)在 Eclipse 中有效但不适用于 .jar 的 loadShader 方法如下:

public static int loadShader(String fileName, int type) {
    final StringBuilder shaderSource = new StringBuilder();
    int shaderID = 0;

    try {
        final BufferedReader reader = new BufferedReader(new FileReader(fileName));
        String line;
        while ((line = reader.readLine()) != null) {
            shaderSource.append(line).append("\n");
        }
        reader.close();
    } catch (final IOException e) {
        System.err.println("Could not read file.");
        e.printStackTrace();
        System.exit(-1);
    }

    shaderID = GL20.glCreateShader(type);
    GL20.glShaderSource(shaderID, shaderSource);
    GL20.glCompileShader(shaderID);

    if (GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
        // Check for any OpenGL errors
        OpenGLHelper.exitOnGLError("Error in quads.QuadUpdateVBO.loadShader()");
    }

    return shaderID;
}

14) 我尝试将其更改为使用 ClassLoader,以便它可以使用 .jar 中打包的资源,但我什至无法让它在 eclipse 中工作。这是我的新方法:

public static int loadShader(String fileName, int type) {
    final StringBuilder shaderSource = new StringBuilder();
    int shaderID = 0;

    try (InputStream shaderStream = QuadUpdateVBO.class.getResourceAsStream(fileName);
            BufferedReader reader = new BufferedReader(new InputStreamReader(shaderStream))) {
        String line;
        while ((line = reader.readLine()) != null) {
            shaderSource.append(line).append("\n");
        }
    } catch (final IOException e) {
        System.err.println("Could not read file.");
        e.printStackTrace();
        System.exit(-1);
    }

    shaderID = GL20.glCreateShader(type);
    GL20.glShaderSource(shaderID, shaderSource);
    GL20.glCompileShader(shaderID);

    if (GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
        // Check for any OpenGL errors
        OpenGLHelper.exitOnGLError("Error in quads.QuadUpdateVBO.loadShader()");
    }

    return shaderID;
}

这是运行 Bootstrap 类时 Eclipse 控制台的输出:

Wed Jul 30 17:58:02 EDT 2014 INFO:Initialising sounds..
[LWJGL] getPathFromClassLoader: searching for: OpenAL32
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException:     sun.misc.Launcher$AppClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException:     java.net.URLClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException:     java.security.SecureClassLoader.findLibrary(java.lang.String)
[LWJGL] getPathFromClassLoader: searching for: lwjgl
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException:     sun.misc.Launcher$AppClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException:     java.net.URLClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException:     java.security.SecureClassLoader.findLibrary(java.lang.String)
[LWJGL] getPathFromClassLoader: searching for: lwjgl
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException:     sun.misc.Launcher$AppClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException:     java.net.URLClassLoader.findLibrary(java.lang.String)
[LWJGL] Failed to locate findLibrary method: java.lang.NoSuchMethodException:     java.security.SecureClassLoader.findLibrary(java.lang.String)
[LWJGL] Found 14 OpenAL paths
[LWJGL] Testing 'C:\Program Files\eclipse\external jars\LWJGL     2.9.2\native\windows\OpenAL64.dll'
[LWJGL] Found OpenAL at 'C:\Program Files\eclipse\external jars\LWJGL     2.9.2\native\windows\OpenAL64.dll'
[LWJGL] MemoryUtil Accessor: AccessorUnsafe
Wed Jul 30 17:58:03 EDT 2014 INFO:- Sound works
Wed Jul 30 17:58:03 EDT 2014 INFO:- 64 OpenAL source available
Wed Jul 30 17:58:03 EDT 2014 INFO:- Sounds source generated
[LWJGL] Initial mode: 1600 x 900 x 32 @60Hz
[LWJGL] Found 32 displaymodes
[LWJGL] Removed 20 duplicate displaymodes
Detected display modes:
800x600x32 60Hz
1600x900x16 60Hz
640x480x16 60Hz
1024x768x16 60Hz
1280x720x32 60Hz
1280x800x16 60Hz
800x600x16 60Hz
1600x900x32 60Hz
640x480x32 60Hz
1024x768x32 60Hz
1280x720x16 60Hz
1280x800x32 60Hz
[LWJGL] GL_EXT_direct_state_access was reported as available but an entry point is     missing
OpenGL version: 3.2.9712 Core Profile Forward-Compatible Context
Exception in thread "main" java.lang.NullPointerException
    at java.io.Reader.<init>(Unknown Source)
    at java.io.InputStreamReader.<init>(Unknown Source)
    at com.fafnir.gestalt.quads.QuadUpdateVBO.loadShader(QuadUpdateVBO.java:194)
    at com.fafnir.gestalt.quads.QuadUpdateVBO.setupShaders(QuadUpdateVBO.java:147)
    at com.fafnir.gestalt.quads.QuadUpdateVBO.<init>(QuadUpdateVBO.java:50)
    at com.fafnir.gestalt.Bootstrap.setupArtists(Bootstrap.java:167)
    at com.fafnir.gestalt.Bootstrap.<init>(Bootstrap.java:72)
    at com.fafnir.gestalt.Bootstrap.main(Bootstrap.java:38)
AL lib: (EE) alc_cleanup: 1 device not closed
Could not locate symbol glEnableClientStateiEXT
Could not locate symbol glDisableClientStateiEXT
Could not locate symbol glGetFloati_vEXT
Could not locate symbol glGetDoublei_vEXT
Could not locate symbol glGetPointeri_vEXT
Could not locate symbol glNamedCopyBufferSubDataEXT
Could not locate symbol glVertexArrayIndexOffsetEXT
Could not locate symbol glVertexArrayVertexAttribOffsetEXT
Could not locate symbol glVertexArrayVertexAttribIOffsetEXT
Could not locate symbol glEnableVertexArrayEXT
Could not locate symbol glDisableVertexArrayEXT
Could not locate symbol glEnableVertexArrayAttribEXT
Could not locate symbol glDisableVertexArrayAttribEXT
Could not locate symbol glGetVertexArrayIntegervEXT
Could not locate symbol glGetVertexArrayPointervEXT
Could not locate symbol glGetVertexArrayIntegeri_vEXT
Could not locate symbol glGetVertexArrayPointeri_vEXT
Could not locate symbol glMapNamedBufferRangeEXT
Could not locate symbol glFlushMappedNamedBufferRangeEXT

最佳答案

想出了一个稳健的方法来回答我自己的问题 - 通过创建一个名为“ResourceHandler”的新类,我设置了一些方法来将字符串作为参数,以及一个 boolean 值(以指示它是否正在加载)是否采用 .getSystemResourceAsStream() 风格)并吐出 BufferedReaders、InputStreams 或 Audio 对象,它们既可以在 Eclipse 中工作,也可以使用 jarsplice 打包在 Fat .jar 中。这是该类的代码:

package com.fafnir.gestalt.helpers;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.net.URL;

import org.newdawn.slick.openal.Audio;
import org.newdawn.slick.openal.AudioLoader;
import org.newdawn.slick.util.ResourceLoader;

public class ResourceHandler {

/**
 * Returns a buffered reader of the input file from a (non/)streaming resource
 * 
 * @param filePath
 * @param streaming
 * @return
 */
public static BufferedReader loadIntoBufferedReader(String filePath, boolean streaming) {
    BufferedReader reader = null;
    if (streaming) {
        InputStream stream = ResourceLoader.getResourceAsStream(filePath);
        InputStreamReader isr = new InputStreamReader(stream);
        reader = new BufferedReader(isr);
    } else {
        URL url = ResourceLoader.getResource(filePath);

        try (FileReader freader = new FileReader(url.toURI().toString())) {
            reader = new BufferedReader(freader);
        } catch (FileNotFoundException fnfe) {
            System.err.println("File " + filePath + " does not exist!");
            fnfe.printStackTrace();
            System.exit(1);
        } catch (URISyntaxException urise) {
            System.err.println("Bad URI syntax for " + filePath + "!");
            urise.printStackTrace();
            System.exit(1);
        } catch (IOException ioe) {
            System.err.println("File " + filePath + " couldn't be read/written to!");
            ioe.printStackTrace();
            System.exit(1);
        }
    }

    return reader;
}

/**
 * Returns an InputStream of the input file
 * 
 * @param filePath
 * @return
 */
public static InputStream loadIntoInputStream(String filePath) {
    InputStream stream = ResourceLoader.getResourceAsStream(filePath);
    return stream;
}

/**
 * Returns an Audio object of the input file as a stream
 * 
 * @param type
 * @param filePath
 * @return
 */
public static Audio loadIntoAudio(String type, String filePath, boolean streaming) {
    Audio audio = null;
    try {
        if (streaming) {
            audio = AudioLoader.getStreamingAudio(type, ResourceLoader.getResource(filePath));
        } else {
            audio = AudioLoader.getAudio(type, ResourceLoader.getResourceAsStream(filePath));
        }
    } catch (final IOException ioe) {
        System.err.println("File " + filePath + " couldn't be read/written to!");
        ioe.printStackTrace();
        System.exit(1);
    }
    return audio;
}

}

关于java - 外部 jar 中的资源加载不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25047912/

相关文章:

maven - 如何从 maven-jar-plugin 中的 jar 中排除 java 文件?

spring-boot - 覆盖作为 jar 一部分的 application.properties 中的 spring 属性

Maven编译一个源码jar依赖

java - 在 Java 的正则表达式中捕获标题大小写组

eclipse - 带有gradle的Eclipse智能

Java泛型,类型丢失

java - Axis 2 错误 : Unable to add the following facets

java - 如何判断虚拟机是在服务器模式下运行还是在客户端模式下运行?

java - 使用 Lambda Java 转换 List 类型

java - 如何在 Java 中序列化 Microsoft Office 对象?