2010-03-07 47 views
2

在过去的几个月里,我一直在为一个大学项目开发​​一个Java游戏。这是即将到项目结束,我想编译成一个易于分发的单个文件的项目。游戏目前从IDE内部运行,并依赖于在特定位置设置的工作目录(即具有声音/纹理等的内容目录)。将所有这些组合在一起以实现可移植性的最佳方式是什么?我希望有一些方法可以将内容编译到jar文件中...发布一个带有内容的Java程序

注意:我使用NetBeans,所以它很容易在NetBeans的任何解决方案中得到加分;)

附录::

以供将来参考,我发现通过目录访问事物的一种方式,ythis可能不是最好的的方式,但它的工作原理:

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

而且现在就可以使用该文件对象为正常

+1

如何使用ant build脚本将所有类和资源文件添加到自我可执行Jar文件中? – Pool 2010-03-07 00:10:33

+0

听起来不错,但我不知道蚂蚁不幸的是:(为什么有人downvote这个? – Martin 2010-03-07 01:49:28

+0

如承诺我已经发布了一些代码作为一个新的答案。它可能会帮助你开始寻找在JAR内的每个目录中的文件 – TofuBeer 2010-03-07 17:36:52

回答

7

您可以将资源嵌入到jar文件中 - 毕竟这只是一个zip文件。标准的做法是将资源文件放在源代码层次的某个目录中。然后通过Object.getClass()。getResourceAsStream()引用它们。所以你需要改变你在代码中检索它们的方式。

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

当你把这些资源文件放到你的src层次结构中时我相信Netbeans应该用你的项目的标准构建来为你打包它们。

+0

这对所有直接使用单个文件的东西都有效,是否有办法将包视为目录并扫描其中的所有文件?这是当前的金砖四国k墙我打了。 – Martin 2010-03-07 02:23:37

+0

@Martin是的,但这并不是微不足道的。我会看看如果我能找到一些代码,我可以做到这一点(很确定我可以......但将是明天)。 – TofuBeer 2010-03-07 05:02:13

+0

你可以使用JarFile,但TofuBeer说它并不那么简单。我会建议一些其他的东西:在构建项目时,您可以预先计算资源列表并将其嵌入到文件中,例如filelist.properties。你读这个文件并知道你拥有的所有资源。 – pajton 2010-03-07 07:58:58

1

那么一种方法是通过Class.getResourceAsStream(或Class.getResource)访问资源。然后确保这些文件在JAR文件中。

关闭我的头顶(而不尝试它),您应该能够将源文件放入源文件中,以便NetBeans将它们放入JAR文件中。然后将File stuff更改为getResource调用。

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

如果你尝试,它不起作用,让我知道,我会看看如果我可以多挖一点(张贴简单的项目的代码将是很好的,如果说到这一点)。

0

是的!把你编译的.class文件和你的资源与文件夹放在一个jar文件中..你将不得不建立一个清单文件以及..你可以找到关于在谷歌上创建一个.jar文件的教程 。很可能你会被引用到java.sun.com。

1

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

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

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

我会做的是看看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. 我认为我发布在this answer中的代码将为您提供一种方法来选择一个临时目录来提取内容。
  4. 我认为我发布在this answer的代码可以帮助将ZipEntry内容复制到文件系统。
  5. 一旦这些项目在文件系统上,您已经拥有的用于迭代目录的代码仍然可以工作。您可以在上面的代码中为FileUtils类添加一个新方法,并能够像现在这样查找所有文件。

有可能是一个更好的方法来做到这一点,但我的头顶我认为这将工作。

+0

那么,我附加到我的答案的技术有什么问题? :/ – Martin 2010-03-07 18:02:31

+0

1)我没有看到它(我只是醒了!) 2)不会返回一个奇怪的URL与JAR!在其中,你不能打开一个文件? – TofuBeer 2010-03-07 18:13:15

+0

恐怕这超出了我对Java Jars文件的理解,你能否给我多一点帮助?可能是 – Martin 2010-03-07 21:49:37