【问题标题】:What could possibly prevent a runnable JAR from opening?什么可能会阻止可运行的 JAR 打开?
【发布时间】:2014-04-20 12:15:06
【问题描述】:

我正在尝试将我的 java 项目(它是一个游戏)导出到一个可运行的 JAR 文件中,但不幸的是,即使我这样做了:文件>导出>Java>可运行的 JAR 文件>正确选择我的主类,当我尝试要打开它,它不会做任何事情(在 Windows 上)或在菜单栏中打开然后意外关闭(在 Mac 上)。

我怀疑这是因为我加载资源的方式。谁能告诉我这可能是什么原因造成的?

编辑:这就是问题所在,我在第一个 for 循环中的 resources.lenght 中得到 NullPointerException:此方法扫描我的资源中的文件夹并读取符合平台类型的每个图像(游戏是平台游戏) 从我的资源中提取并将它们保存在 ArrayList 中。

private void readImages() {
    URL urlFolder = getClass().getClassLoader().getResource("platforms");
    File[] resources = new File(urlFolder.getPath()).listFiles();
    for(int i = 0; i < resources.length; i++) {
        String fileName = resources[i].getName();
        String name = fileName.substring(0,          fileName.indexOf('_')).toUpperCase();
        try {
            EnumPlatformTypes type = EnumPlatformTypes.valueOf(name);
            variantsForType[getTypeNumber(type)]++;
        } catch(Exception e) {
            System.out.println("Erreur de nommage du fichier " + fileName);
        }
    }

    for(int i = 0; i < NUMBER_OF_TYPES; i++) {
        platformSprites.add(new Image[variantsForType[i]]);
        String type = EnumPlatformTypes.values()[i].toString();
        for(int k = 0; k < variantsForType[i] ; k++) {
            String fileName = type.substring(0, 1) + type.substring(1, type.length()).toLowerCase() + "_" + k + ".png";
            URL url = getClass().getClassLoader().getResource("platforms/" + fileName);
            if(url == null) {
                System.out.println("Incapable de lire le fichier d'image " + fileName);
                return;
            }
            try {
                platformSprites.get(i)[k] = ImageIO.read(url);
            } catch(IOException e) {
                System.out.println("IOException lors de la lecture     avec ImageIO");
            }   
        }
    }
}

如果您知道此代码是否可以阻止打开罐子,如果您能告诉我问题出在哪里,我将不胜感激。

谢谢。

【问题讨论】:

  • 使用java -jar &lt;file&gt; 运行JAR,这样您就可以看到错误是什么。将堆栈跟踪添加到您的问题中。
  • 尝试从命令行运行它 (java -jar ...)。你的任何错误都会被打印出来吗?
  • (感谢我不知道的命令)所以错误是这一行上的 nullPointerException:for(int i = 0; i
  • File[] resources = new File(urlFolder.getPath()).listFiles();
  • 另外,不要抓住Exception!这还将捕获所有未经检查的异常(包括NullPointerException 等)

标签: java image file jar resources


【解决方案1】:

你说异常发生在这里:

URL urlFolder = getClass().getClassLoader().getResource("platforms");
File[] resources = new File(urlFolder.getPath()).listFiles();
for(int i = 0; i < resources.length; i++) {            // THIS LINE

这意味着resourcesnull

这反过来意味着listFiles()返回了null

这意味着无论 urlFolder.getPath() 返回什么都不是文件系统中目录的可解析路径名。 (见javadoc for listFiles()),

这是预期的……如果“平台”资源在 JAR 文件中。 (在这种情况下,URL 将是一个“jar:” URL,getPath() 不会返回您需要的内容。事实上,它不能,因为您需要的目录名称根本不在文件系统中。)

这是一个问题,其答案提供了一些可能的解决方案:

...但它并不漂亮。或@fge 的 Java 7+ 解决方案。

【讨论】:

  • Java 7 比最后一个答案中提出的解决方案要容易得多;)
【解决方案2】:

鉴于您使用 Java 7,这是一个应该可以工作的解决方案...“诀窍”是使用新的文件 API。 Oracle JDK 提供了一个FileSystem 实现,可用于查看/修改 ZIP 文件,包括 jar!

预赛:抢System.getProperty("java.class.path", "."),对战:;这将为您提供定义的类路径中的所有条目。

首先,定义一个从类路径条目中获取FileSystem 的方法:

private static final Map<String, ?> ENV = Collections.emptyMap();

//

private static FileSystem getFileSystem(final String entryName)
    throws IOException
{
    final String uri = entryName.endsWith(".jar") || entryName.endsWith(".zip"))
        ? "jar:file:" + entryName : "file:" + entryName;
    return FileSystems.newFileSystem(URI.create(uri), ENV);
}

然后创建一个方法来判断文件系统中是否存在路径:

private static boolean pathExists(final FileSystem fs, final String needle)
{
    final Path path = fs.getPath(needle);
    return Files.exists(path);
}

用它来定位您的"platform"

一旦你有了正确的FileSystem,就可以使用上面的.getPath() 遍历你的目录,并使用Files.newDirectoryStream() 打开一个DirectoryStream

完成后不要忘记 .close() 文件系统!


编辑 1 这是一个示例 main(),演示如何读取 jar 的所有根条目:

public static void main(final String... args)
    throws IOException
{
    final Map<String, ?> env = Collections.emptyMap();
    final String jarName = "/opt/sunjdk/1.6/current/jre/lib/plugin.jar";
    final URI uri = URI.create("jar:file:" + jarName);
    final FileSystem fs = FileSystems.newFileSystem(uri, env);
    final Path dir = fs.getPath("/");
    for (Path entry : Files.newDirectoryStream(dir))
        System.out.println(entry);
}

EDIT 2这是一个示例 main,它允许您打印类路径的内容以及与之关联的 MIME 类型:

public final class Foo
{
    public static void main(final String... args)
    {
        final ClassLoader loader = Foo.class.getClassLoader();

        final URL[] urLs = ((URLClassLoader) loader).getURLs();

        for (final URL url : urLs) {
            System.out.println(url);
            System.out.println(Files.probeContentType(Paths.get(url.toURI())));
        }
    }
}

你会看到Files.probeContentType()的返回码是:

  • application/x-java-archive 用于 JAR,
  • inode/directory 用于目录。

这意味着您可以使用此方法的返回码来构建正确的 URI,从而打开正确的FileSystem

【讨论】:

  • 您应该将其添加为我链接到的问题的答案!
  • 当我尝试使用 System.getProperty("java.class.path", ".") 获取路径并将该路径转换为 ​​URI 时,我收到错误,因为路径包含反斜杠。你知道我做错了什么吗?
  • @user3421883 使用 Windows? ;) 开个玩笑……我知道该怎么做才能防止这个错误。等待后期更新
猜你喜欢
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 1970-01-01
  • 2021-04-17
  • 1970-01-01
相关资源
最近更新 更多