使用内容分发Java程序

在过去的几个月里,我一直在为一个大学项目开发​​java游戏。 它即将到达项目的最后阶段,我想将项目编译成一个易于分发的文件。 游戏当前从IDE内部运行,并依赖于特定地设置的工作目录(即具有声音/纹理的内容目录等)。 将所有这些放在一起以便携带的最佳方法是什么? 我希望有一些方法可以将内容编译到jar文件中……

NB。 我正在使用NetBeans,因此任何易于使用netbeans的解决方案都会获得额外的功劳;)

附录::

为了将来的参考,我找到了一种按目录访问东西的方法,这可能不是最好的方法,但它有效:

File directory = new File(ClassLoader.getSystemResource("fullprototypeone/Content/Levels/").toURI()); 

现在我可以正常使用该文件对象

你可以在jar文件中嵌入资源 – 毕竟这只是一个拉链。 执行此操作的标准方法是将资源文件放在源层中的某个目录中。 然后由Object.getClass()。getResourceAsStream()引用它们。 因此,您需要更改在代码中检索它们的方式。

你可以在这里阅读更多: Object.getClass()。getResourceAsStream() 。 当然,您可以使用包中的某些类而不是对象。

当你把这些资源文件放在你的src层次结构中时,我相信Netbeans应该用标准版本的项目来为你设计它们。

这是JNLP和Java Web Start的手册。 这些技术仅适用于您所描述的任务。

一种方法是通过Class.getResourceAsStream(或Class.getResource)访问资源。 然后确保文件位于JAR文件中。

在我的脑海中(并且没有尝试)你应该能够将资源放入源文件中,这将使NetBeans将它们放入JAR文件中。 然后将File stuff更改为getResource调用。

我建议制作一个简单的程序播放声音并在尝试转换整个项目之前尝试一下。

如果你尝试它并不起作用,请告诉我,我会看看我是否可以深入研究它(如果涉及这个问题,发布简单项目的代码会很好)。

这是我在另一条评论中承诺的代码……这不是我记得的,但它可能会让你开始。

基本上你调用:String fileName = FileUtils.getFileName(Main.class,“foo.txt”);

它会在磁盘或JAR文件中找到该文件。 如果它在JAR文件中,则将其提取到临时目录。 然后,您可以使用“新文件(fileName)”打开文件,无论以前在哪里,都将在磁盘上。

我要做的是看看getFile方法,看看你可以用JAR文件做什么来迭代它的内容并找到给定目录中的文件。

就像我说的,不完全是你想要的,但确实为你做了很多初步的工作。

 import java.io.Closeable; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLDecoder; import java.security.CodeSource; import java.security.ProtectionDomain; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; public class FileUtils { public static String getFileName(final Class owner, final String name) throws URISyntaxException, ZipException, IOException { String fileName; final URI uri; try { final String external; final String decoded; final int pos; uri = getResourceAsURI(owner.getPackage().getName().replaceAll("\\.", "/") + "/" + name, owner); external = uri.toURL().toExternalForm(); decoded = external; // URLDecoder.decode(external, "UTF-8"); pos = decoded.indexOf(":/"); fileName = decoded.substring(pos + 1); } catch(final FileNotFoundException ex) { fileName = null; } if(fileName == null || !(new File(fileName).exists())) { fileName = getFileNameX(owner, name); } return (fileName); } private static String getFileNameX(final Class clazz, final String name) throws UnsupportedEncodingException { final URL url; final String fileName; url = clazz.getResource(name); if(url == null) { fileName = name; } else { final String decoded; final int pos; decoded = URLDecoder.decode(url.toExternalForm(), "UTF-8"); pos = decoded.indexOf(":/"); fileName = decoded.substring(pos + 1); } return (fileName); } private static URI getResourceAsURI(final String resourceName, final Class clazz) throws URISyntaxException, ZipException, IOException { final URI uri; final URI resourceURI; uri = getJarURI(clazz); resourceURI = getFile(uri, resourceName); return (resourceURI); } private static URI getJarURI(final Class clazz) throws URISyntaxException { final ProtectionDomain domain; final CodeSource source; final URL url; final URI uri; domain = clazz.getProtectionDomain(); source = domain.getCodeSource(); url = source.getLocation(); uri = url.toURI(); return (uri); } private static URI getFile(final URI where, final String fileName) throws ZipException, IOException { final File location; final URI fileURI; location = new File(where); // not in a JAR, just return the path on disk if(location.isDirectory()) { fileURI = URI.create(where.toString() + fileName); } else { final ZipFile zipFile; zipFile = new ZipFile(location); try { fileURI = extract(zipFile, fileName); } finally { zipFile.close(); } } return (fileURI); } private static URI extract(final ZipFile zipFile, final String fileName) throws IOException { final File tempFile; final ZipEntry entry; final InputStream zipStream; OutputStream fileStream; tempFile = File.createTempFile(fileName.replace("/", ""), Long.toString(System.currentTimeMillis())); tempFile.deleteOnExit(); entry = zipFile.getEntry(fileName); if(entry == null) { throw new FileNotFoundException("cannot find file: " + fileName + " in archive: " + zipFile.getName()); } zipStream = zipFile.getInputStream(entry); fileStream = null; try { final byte[] buf; int i; fileStream = new FileOutputStream(tempFile); buf = new byte[1024]; i = 0; while((i = zipStream.read(buf)) != -1) { fileStream.write(buf, 0, i); } } finally { close(zipStream); close(fileStream); } return (tempFile.toURI()); } private static void close(final Closeable stream) { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } } 

编辑:

对不起,我现在没有时间处理这个问题(如果我得到一些,我会这样做并在此处发布代码)。 这是我会做的事情:

  1. 查看ZipFile类并使用entries()方法查找zip文件中的所有文件/目录。
  2. ZipEntry有一个isDirectory()方法,您可以使用它来弄清楚它是什么。
  3. 我认为我在这个答案中发布的代码将为您提供一种方法来选择一个临时目录来提取内容。
  4. 我认为我在这个答案中发布的代码可以帮助将ZipEntry内容复制到文件系统。
  5. 一旦项目在文件系统上,您已经拥有的用于遍历目录的代码仍然有效。 您可以在上面的代码中向FileUtils类添加一个新方法,并且能够像现在一样找到所有文件。

可能有更好的方法来做到这一点,但我认为这将起作用。

是的! 将您编译的.class文件和资源与文件夹放在一个jar文件中……你还必须构建一个清单文件..你可以找到关于在google上制作.jar文件的教程。 最有可能你会被提到java.sun.com。