我试图将我的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打开,我很高兴您能告诉我问题在哪里。
感谢。
答案 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
这意味着resources
是null
。
这反过来意味着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
。