什么可能阻止可运行的JAR打开?

时间:2014-03-15 00:19:24

标签: java image file jar resources

我试图将我的java项目(它的游戏)导出到一个可运行的JAR文件中,但不幸的是,即使我这样做了:文件>导出> Java> Runnable 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");
            }   
        }
    }
}

如果您知道此代码是否可以阻止jar打开,我很高兴您能告诉我问题在哪里。

感谢。

2 个答案:

答案 0 :(得分:2)

你说这里发生了异常:

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+解决方案。

答案 1 :(得分:1)

这是一个解决方案,应该可以使用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()浏览您的目录,并使用DirectoryStream打开Files.newDirectoryStream()

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


编辑1 以下是演示如何阅读jar的所有根条目的示例main()

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